I was experimenting with some intersection between common primitive types in Typescript.
By default null and undefined are subtypes of all other types. That means you can assign null and undefined to something like number.
However, when using the --strictNullChecks flag, null and undefined are only assignable to unknown, any and their respective types (the one exception being that undefined is also assignable to void). This helps avoid many common errors. In cases where you want to pass in either a string or null or undefined, you can use the union type string | null | undefined.
Here are the tests I've run:
// --strictNullChecks DISABLED
type BOOLEAN_STRING = boolean & string; // NEVER
type BOOLEAN_NUMBER = boolean & number; // NEVER
type BOOLEAN_UNDEFINED = boolean & undefined; // UNDEFINED
type BOOLEAN_NULL = boolean & null; // NULL
type STRING_NUMBER = string & number; // string & number
type STRING_UNDEFINED = string & undefined; // UNDEFINED
type STRING_NULL = string & null; // NULL
type NUMBER_UNDEFINED = number & undefined; // UNDEFINED
type NUMBER_NULL = number & null; // NULL
Given the fact that null
and undefined
are subtypes of all other types (when --strictNullChecks
is disabled), I guess all results make sense, except for one:
type STRING_NUMBER = string & number; // string & number
Shouldn't string & number
be never?
I also ran the test with --strictNullChecks
enabled.
// --strictNullChecks ENABLED
type BOOLEAN_STRING = boolean & string; // NEVER
type BOOLEAN_NUMBER = boolean & number; // NEVER
type BOOLEAN_UNDEFINED = boolean & undefined; // NEVER
type BOOLEAN_NULL = boolean & null; // NEVER
type STRING_NUMBER = string & number; // string & number
type STRING_UNDEFINED = string & undefined; // string & undefined
type STRING_NULL = string & null; // string & null
type NUMBER_UNDEFINED = number & undefined; // number & undefined
type NUMBER_NULL = number & null; // number & null
Given the fact that with strictNullChecks
undefined
and null
are only assignable to unknown
and any
, shouldn't all the following be evaluated as never
, instead of the intersection?
type STRING_UNDEFINED = string & undefined; // string & undefined
type STRING_NULL = string & null; // string & null
type NUMBER_UNDEFINED = number & undefined; // number & undefined
type NUMBER_NULL = number & null; // number & null