Problem
Home narrows value inside a positive instanceof branch, but when that branch assigns a replacement value and falls through, it does not join the false path with the assigned true path.
Canonical example:
let result: Payload | Promise<Payload> = load();
if (result instanceof Promise) result = await result;
result.issues.map((issue) => issue);Both reachable paths leave result as Payload. TypeScript 6.0.3 and native tsgo 7.0.2 therefore contextually type issue from Payload.issues. This was discovered while reducing #688, but it is a standalone control-flow rule rather than an imported-schema workaround.
Required behavior
- Recognize a positive
x instanceof Tguard whose then-branch assigns back tox. - Subtract
Tfrom the false path and join it with the assigned true-path type. - Coalesce structurally identical types rather than retaining a redundant union.
- Preserve existing negated-guard and terminating-branch behavior.
- Add no project- or library-specific cases.
Verification
- Focused oracle: Home, TypeScript 6.0.3, and native tsgo 7.0.2 agree exactly on the diagnostic code/location multiset (TS2322 at 13:11 and TS2339 at 14:11; no TS7006).
- Full
ts_checkersuite passes. - Zod 4.5.2
src/v4/core/**/*.tsremains exactly diagnostic-identical to origin/main: 150 diagnostics, zero additions/removals. - ReleaseSafe
home-tscbuild passes. - Every heavy command was serialized under the repository guard with a fixed 3840 MB maximum.
Follow-up
This closes only the assignment-flow portion found during #688. The qualified imported issue-array projection remains open there; rejected broad projection attempts caused either a candidate-only bus error or extra Zod diagnostics and must not be landed.