Introduction
Type narrowing helps TypeScript understand exactly what kind of value you are working with. This makes your code safer and helps avoid mistakes.
Type narrowing helps TypeScript understand exactly what kind of value you are working with. This makes your code safer and helps avoid mistakes.
if (typeof variable === 'string') { // variable is treated as string here } else if (typeof variable === 'number') { // variable is treated as number here }
typeof, instanceof, or custom type guards.x to string or number so you can safely use string or number methods.function printLength(x: string | number) { if (typeof x === 'string') { console.log(x.length); } else { console.log(x.toFixed(2)); } }
value to a Date type.function isDate(value: unknown): value is Date { return value instanceof Date; } function printDate(value: unknown) { if (isDate(value)) { console.log(value.toISOString()); } else { console.log('Not a date'); } }
This program shows how type narrowing lets us handle different types safely and clearly.
function describe(value: string | number | boolean) { if (typeof value === 'string') { console.log(`String with length ${value.length}`); } else if (typeof value === 'number') { console.log(`Number with fixed 2 decimals: ${value.toFixed(2)}`); } else { console.log(`Boolean value: ${value}`); } } describe('hello'); describe(3.14159); describe(true);
Without type narrowing, TypeScript would not know which methods are safe to call.
Type narrowing helps catch bugs early by making sure you only use values in ways that make sense.
Type narrowing tells TypeScript the exact type of a variable at a certain point.
This makes your code safer and easier to understand.
Use type narrowing whenever you work with variables that can have multiple types.
typeof checks like typeof value === 'string' narrows the type inside the block.as, let value: any = 5; value = 'hello'; uses any without narrowing, function test(value: number | string) { return value; } does not narrow inside function.function printLength(x: string | number) {
if (typeof x === 'string') {
return x.length;
} else {
return x.toFixed(2);
}
}
console.log(printLength('hello'));
console.log(printLength(3.14159));if checks if x is a string, then returns its length (5 for 'hello'). Else, it treats x as number and calls toFixed(2).toFixed(2) returns '3.14'.function process(value: string | number) {
console.log(value.length);
}value can be string or number, but length exists only on string.length on number causes error. Type narrowing is needed to safely access length.string | number | null. You want to safely return the string length or number fixed to 1 decimal, or 0 if null. Which code correctly uses type narrowing?x is null, which is correct.typeof to check string and number separately, calling correct methods safely.x.length || x.toFixed(1) without narrowing; function format(x: string | number | null) {
return x.length ?? x.toFixed(1) ?? 0;
} uses nullish coalescing incorrectly; function format(x: string | number | null) {
if (typeof x === 'number') return x.length;
else if (typeof x === 'string') return x.toFixed(1);
else return 0;
} swaps methods for types.Pass the test and this pattern moves unknown