TSworkingts-evergreen

Type Narrowing

Trust the compiler.

TypeScript narrows union types based on the operations you use against them β€” typeof, instanceof, in, and custom type guards. Knowing the rules saves casts.

typeof, instanceof, in

The three free narrowers: typeof x === 'string' removes non-string variants, x instanceof Error keeps only Error subclasses, and 'foo' in x keeps variants that have the foo property.

Custom type guards

A function with : arg is T return type tells the compiler that, if it returns true, the argument is of type T inside the calling branch. Useful for unions of interfaces that don't share a discriminant.

Truthiness narrowing

if (x) narrows string | null | undefined | 0 | '' down to non-falsy values. Combine with non-null assertions sparingly β€” usually the narrowing is enough.

More narrowers in practice

The in operator shines on payload unions that share no discriminant tag. instanceof and Array.isArray narrow class instances and arrays out of broader unknown/object types. And pairing a discriminated union with a never-typed default makes the compiler enforce exhaustiveness β€” add a variant, and forgetting to handle it becomes a type error.

Try it 5 examples

typeof and in

TSintro
Press Run to execute

typeof a === 'string' peels the string off the parameter, then 'lives' in a and 'goodBoy' in a pick out the object variants by a property only they have β€” producing named Whiskers, cat with 9 lives, good dog, fish. Inside each branch a is narrowed enough that a.lives and a.goodBoy are accessible without a cast.