How to enforce strict typing when setting a variable?

204 Views Asked by At

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?

2

There are 2 best solutions below

0
Guillaume Brunerie On BEST ANSWER

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.

1
Andreas On

Without a schema, yaml.load cannot know what it is expected to read, so it will parse and return anything that is valid yaml. Type coercion in TS doesn't validate anything, instead it just communicates to the compiler that you know what the type is.

More to the point, if you want to ensure that your input has a given structure and type, you either need to validate the data yourself or use a library that does that for you.