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