Search code examples
typescripttypescastingcoercion

How to enforce strict typing when setting a variable?


I would like to ensure that the data I read from a YAML file is aligned with the type of the variable it goes into:

type Http = {
  name: string
  api: string
  resp: number
  status: string
  statusEffective: string
}

export const monitorHttp = () => {
  const conf = getConf("conf-http.yml") as Http[]
  log.info("", conf)
}

getConf is defined as

export const getConf = (file: string) => {
  try {
    return yaml.load(fs.readFileSync(`../data/${file}`, "utf8"))
  } catch {
    log.error("cannot load config.yaml, aborting")
    process.exit(1)
  }
}

What is therefore returned by getConf is of type any there will be various structures for different .yml files).

I was expecting that by coercing conf to be Http[] only data with this structure would be accepted.

It is not true however, by sending fields that do not exist in Http the program still runs fine. With a YAML file containing

- name: jellyfin
  api: http://jellyfin.xxxx
  resp: 200
  status: enabled
  wazaa: wazii

I get the result

2023-02-26 17:55:49.979 INFO    \W\dev-perso\hass-monitoring\src\monitor-http.ts:14         [
  {
    name: 'jellyfin',
    api: 'http://jellyfin.xxxx',
    resp: 200,
    status: 'enabled',
    wazaa: 'wazii'
  }
]

Why does the program run fine despite wazaa not existing in Http? Or, more specifically: how to enforce a strict type checking when initializing or updating a variable?


Solution

  • You can use the zod library for runtime validation.

    You'll need to define a schema in a slightly different language than Typescript, and then you'll automatically get a Typescript type and a function for parsing an arbitrary value against this schema.