Commit 27e7d59
Add comment explaining why instanceof UnionType is the correct guard
The `instanceof UnionType` check in filterBySpecifiedTypes is a structural
check (is this type an explicit union of alternatives?), not a semantic
type check (is this a string/int/etc?). It's the correct restriction because:
- Union types represent disjunctions: narrowing to one member validly
satisfies the guard condition (e.g., 1|2 narrowed to 1)
- Non-union types like IntersectionType can have coincidental subtype
relationships that cause incorrect type narrowing when the conditional
result is applied (e.g., non-falsy-string with 'filter' as subtype)
- BooleanType (which represents true|false but is not a UnionType) must be
excluded because template conditional types create per-branch conditionals
that would conflict via subtype matching
Alternative approaches explored and rejected:
- TypeCombinator::remove-based check: correctly handles unions and
intersections, but incorrectly allows BooleanType guards (causing
*NEVER* type in template conditional assertions like bug-14249)
- !instanceof MixedType: too permissive, allows intersection type guards
- getFiniteTypes() > 1: too restrictive, excludes non-finite unions
like int|string
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>1 parent c90cbe5 commit 27e7d59
1 file changed
+7
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3227 | 3227 | | |
3228 | 3228 | | |
3229 | 3229 | | |
| 3230 | + | |
| 3231 | + | |
| 3232 | + | |
| 3233 | + | |
| 3234 | + | |
| 3235 | + | |
| 3236 | + | |
3230 | 3237 | | |
3231 | 3238 | | |
3232 | 3239 | | |
| |||
0 commit comments