"Every narrowing operator we've seen is one ingredient. Control flow analysis is the chef."
What CFA is
Control flow analysis (CFA) is the compiler's process of reading your code line by line and tracking what each variable's type is at every point. It's not a separate feature — it's the engine that makes all the narrowing operators we've covered work together.
The compiler walks every branch of every if, every case in every switch, every early return, every assignment, every throw. After each operation, it updates its model of what each variable's type is. By the time control reaches a line, the compiler knows the narrowest possible type for each variable based on everything that came before.
Early returns narrow the rest of the function
This is the cleanest CFA pattern. Check for the bad case, return early, and the rest of the function sees the narrowed type.
function process(x: User | null) {
if (x === null) return;
// x: User from here to the end of the function
console.log(x.name); // safe — x is non-null
}
The compiler is reading the early return and inferring: "after this line, x can't be null." The rest of the function is automatically scoped under that constraint.
Assignments and reassignments
CFA tracks assignments too. let x: string | null = getMaybe(); followed by if (x === null) x = 'default'. After the if, x is string — the reassignment removed null from the possibilities at that point.
One subtlety: this works for let, not const (because const can't be reassigned). And it works only inside the function — the variable's *declared* type stays whatever you wrote; the narrowed type is just what the compiler's tracking at each point.
Function calls reset narrowing (sometimes)
CFA assumes function calls might mutate things. If you narrow a variable, call a function, and then try to use the narrow type, the compiler may have widened it again. The reason: between your narrowing and your use, the function call could have reassigned. For local variables (where you can see all writes), this is conservative. For object properties, it's the right call.