Control Flow & Type Guards
How TypeScript reads your if/else statements to narrow types.
Watching your code execute
When you have a Union Type like string | number, TypeScript is pessimistic: it won't let you use string methods or number methods because it doesn't know which one it is.
However, TypeScript's compiler is smart enough to read your control flow (if, else, switch, return). If you write standard JavaScript code to check the type, TypeScript updates its understanding of the variable inside that specific block.
Type Narrowing
This process is called 'Type Narrowing'. A 'Type Guard' is just a standard JavaScript expression (like typeof x === "string") that TypeScript recognizes as a way to narrow a type.
This allows you to write perfectly natural JavaScript code while getting strict type safety.
Using typeof as a Type Guard
typescript
function printId(id: string | number) {
// Error: Property 'toUpperCase' does not exist on type 'number'
// id.toUpperCase();
if (typeof id === "string") {
// TypeScript now knows 'id' is a string here!
console.log(id.toUpperCase());
} else {
// TypeScript knows 'id' MUST be a number here!
console.log(id.toFixed(2));
}
}
Try it
Select a runtime value and watch how TypeScript narrows the string | number union based on the if/else execution path.
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- TypeScript reads your
if/elsecontrol flow to narrow types. - A Type Guard is a JS expression that narrows a TS type.
typeof val === 'string'narrows a union down to a string.- Extracting a type guard to a normal function breaks the narrowing.
Done with this concept?
Mark it complete to track your progress. No login needed.