Control Flow Analysis
In this page:
Narrowing with typeof
TypeScript uses typeof checks inside conditional branches to narrow a primitive union type — inside an if (typeof x === "string") block, x is treated as exactly string for the rest of that branch.
Example: Narrowing with typeof
function print(x: string | number) {
if (typeof x === "string") {
console.log(x.toUpperCase());
} else {
console.log(x.toFixed(2));
}
}
print("hello");
Truthiness Narrowing
TypeScript can eliminate null, undefined, false, 0, and other falsy possibilities from a type just by checking a value for truthiness in an if statement, without needing an explicit typeof or instanceof check.
Example: Truthiness Narrowing
function printLength(x: string | null | undefined) {
if (x) {
console.log(x.length);
} else {
console.log("no value");
}
}
printLength("hello");
printLength(null);
Equality Narrowing
Equality checks narrow types too, especially useful when comparing a union value against one specific literal — after if (status === "error"), TypeScript knows status is exactly the literal type "error" in that branch.
Example: Equality Narrowing
type Status = "success" | "error" | "pending";
function handle(status: Status) {
if (status === "error") {
console.log("Something went wrong");
} else {
console.log("Status:", status);
}
}
handle("error");
Assignments and Control Flow
TypeScript analyzes plain assignments as part of control flow, so a variable can be narrowed based on the value it currently holds even when its declared type is a much wider union.
Example: Assignments and Control Flow
let value: string | number;
value = "hello";
console.log(value.toUpperCase());
value = 42;
console.log(value.toFixed(1));
Narrowing Across Functions
Control flow analysis works together with return statements and type guards — once a branch returns or throws, TypeScript can use that fact to narrow the type in whatever code comes after it.
Example: Narrowing Across Functions
function process(x: string | null) {
if (x === null) {
return;
}
console.log(x.toUpperCase());
}
process("hello");
process(null);
Chapter Quiz — Complete all 20 topics to unlock
0/20 topics done
Complete these topics first:
- TypeScript Advanced Types
- Mapped Types
- Conditional Types
- Custom Type Guards
- Assertion Functions
- Control Flow Analysis
- Exhaustiveness Checking
- Satisfies Operator
- Template Literal Types
- Utility Types - Partial
- Utility Types - Required
- Utility Types - Readonly
- Utility Types - Pick
- Utility Types - Omit
- Utility Types - Record
- Utility Types - Exclude and Extract
- Utility Types - NonNullable
- Utility Types - ReturnType
- Utility Types - Parameters
- TypeScript 5 Updates