diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6a42dc43d51..ca0d61c8106 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7555,7 +7555,7 @@ namespace ts { } function getNarrowedTypeOfReference(type: Type, reference: Node) { - if (!(type.flags & TypeFlags.Narrowable) || !isNarrowableReference(reference)) { + if (type.flags & TypeFlags.Defaultable || !isNarrowableReference(reference)) { return type; } const leftmostNode = getLeftmostIdentifierOrThis(reference); @@ -7975,7 +7975,7 @@ namespace ts { const defaultsToDeclaredType = !strictNullChecks || type.flags & TypeFlags.Any || !declaration || declaration.kind === SyntaxKind.Parameter || isInAmbientContext(declaration) || getContainingFunctionOrModule(declaration) !== getContainingFunctionOrModule(node); - if (defaultsToDeclaredType && !(type.flags & TypeFlags.Narrowable)) { + if (defaultsToDeclaredType && type.flags & TypeFlags.Defaultable) { return type; } const flowType = getFlowTypeOfReference(node, type, defaultsToDeclaredType ? type : undefinedType); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d0d411a710e..5f181bc982e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2175,7 +2175,13 @@ namespace ts { ObjectType = Class | Interface | Reference | Tuple | Anonymous, UnionOrIntersection = Union | Intersection, StructuredType = ObjectType | Union | Intersection, - Narrowable = Any | ObjectType | Union | TypeParameter, + + // 'Defaultable' types are types where narrowing reverts to the original type, rather than actually narrow. + // This is never really correct - you can _always_ narrow to an intersection with that type, _but_ we keep + // Void as the only defaultable type, since it's a non-value type construct (representing a lack of a value) + // and, generally speaking, narrowing `void` should fail in some way, as it is nonsensical. (`void` narrowing + // to `void & T`, in a structural sense, is just narrowing to T, which we wouldn't allow under normal rules) + Defaultable = Void, /* @internal */ RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral, /* @internal */