Flow联合类型判断未触发预期类型错误问题咨询
Let's start by looking at your code to ground the discussion:
type Something = | { t: 'A', src: string } | { t: 'B', src: string } | { t: 'C', src: number }; const f = (o: Something): string => o.t === 1 ? o.src : 'a-string';
The Core Difference: Flow vs. TypeScript on Unreachable Code
The behavior you're seeing comes down to how each type checker handles provably unreachable code paths.
Your Something union type restricts t to the string literals 'A', 'B', or 'C'—there is zero possibility for o.t to ever equal the number 1. Flow recognizes this: the condition o.t === 1 will always evaluate to false, so the branch where you return o.src will never execute at runtime.
Because Flow knows this branch is unreachable, it skips strict type checking for that code path. It doesn't waste time validating whether o.src matches the function's return type string, since that code will never run anyway.
Why TypeScript Flags an Error
TypeScript takes a more rigid approach here. Even when it can detect a branch is unreachable, it still enforces type compatibility across all code paths. In your example, TypeScript flags the o.src return because if (hypothetically) that branch were entered, o.src could be a number (when t is 'C'), which doesn't align with the required return type string.
Test This Behavior Yourself
To confirm this logic, modify the condition to one that's actually reachable:
const f = (o: Something): string => o.t === 'C' ? o.src : 'a-string';
Now Flow will throw a type error, because o.src is a number when t is 'C'—and this branch is reachable, so Flow enforces the return type constraint as expected.
Summary
This isn't a flaw in Flow—it's a deliberate design choice. Flow prioritizes practicality by skipping checks for code that can never run, while TypeScript enforces strict type safety across all code paths, regardless of whether they're reachable.
内容的提问来源于stack exchange,提问作者Sam R.

