linkedlist:

Distinguish "missing" and "undefined" in TypeScript

#33 · · TypeScript

Currently, it is not possible to properly distinguish the undefined value type from a missing value. For example, when defining a type for a plain object literal, you can't specify that a certain property may be missing but must not be undefined when specified. TypeScript accepts all the following object literal definitions except the annotated line.

type T1 = {foo?: string}
const t1a: T1 = {}
const t1b: T1 = {foo: 'bar'}
const t1c: T1 = {foo: undefined}

type T2 = {foo: string | undefined}
const t2a: T2 = {} // fails: Property 'foo' is missing in type '{}' but required in type 'T2'.
const t2b: T2 = {foo: 'bar'}
const t2c: T2 = {foo: undefined}

That will likely change, though. There is a PR that adds the new config flag --strictOptionalProperties to configure that behaviour. It will also be in the strict config family which means that enabling --strict will include --strictOptionalProperties. If either one of those flags is used, foo?:string means that the foo property either is absent or must be a string. It cannot be defined as undefined. Note that this configuration does not have any influence on accessing non-existing properties. That would still evaluate to undefined.

// Will fail with --strictOptionalProperties or --strict:
// Types of property 'foo' are incompatible.
// Type 'undefined' is not comparable to type 'string'.
const t1a: T1 = {foo: undefined}

const t1b: T1 = {}
t1b.foo // still works the same and evaluates to `undefined`

The milestone of this PR is currently set to TypeScript 4.4.0. As of now, this version has not yet been released.