Skip to content

Commit b3d3ec9

Browse files
committed
Use strictSubtypeRelation in getNarrowedType and narrow only for pure subtypes
1 parent e9868e9 commit b3d3ec9

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

src/compiler/checker.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -19108,6 +19108,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1910819108
return isTypeRelatedTo(source, target, subtypeRelation);
1910919109
}
1911019110

19111+
function isTypeStrictSubtypeOf(source: Type, target: Type): boolean {
19112+
return isTypeRelatedTo(source, target, strictSubtypeRelation);
19113+
}
19114+
1911119115
function isTypeAssignableTo(source: Type, target: Type): boolean {
1911219116
return isTypeRelatedTo(source, target, assignableRelation);
1911319117
}
@@ -27250,7 +27254,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2725027254
}
2725127255
// We first attempt to filter the current type, narrowing constituents as appropriate and removing
2725227256
// constituents that are unrelated to the candidate.
27253-
const isRelated = checkDerived ? isTypeDerivedFrom : isTypeSubtypeOf;
27257+
const isRelated = checkDerived ? isTypeDerivedFrom : isTypeStrictSubtypeOf;
2725427258
const keyPropertyName = type.flags & TypeFlags.Union ? getKeyPropertyName(type as UnionType) : undefined;
2725527259
const narrowedType = mapType(candidate, c => {
2725627260
// If a discriminant property is available, use that to reduce the type.
@@ -27260,9 +27264,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2726027264
// specific of the two. When t and c are related in both directions, we prefer c for type predicates
2726127265
// because that is the asserted type, but t for `instanceof` because generics aren't reflected in
2726227266
// prototype object types.
27263-
const directlyRelated = mapType(matching || type, checkDerived ?
27264-
t => isTypeDerivedFrom(t, c) ? t : isTypeDerivedFrom(c, t) ? c : neverType :
27265-
t => isTypeSubtypeOf(c, t) && !isTypeIdenticalTo(c, t) ? c : isTypeSubtypeOf(t, c) ? t : neverType);
27267+
const directlyRelated = mapType(matching || type, t => isRelated(t, c) ? t : isRelated(c, t) ? c : neverType);
2726627268
// If no constituents are directly related, create intersections for any generic constituents that
2726727269
// are related by constraint.
2726827270
return directlyRelated.flags & TypeFlags.Never ?
@@ -27272,7 +27274,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2727227274
// If filtering produced a non-empty type, return that. Otherwise, pick the most specific of the two
2727327275
// based on assignability, or as a last resort produce an intersection.
2727427276
return !(narrowedType.flags & TypeFlags.Never) ? narrowedType :
27275-
isTypeSubtypeOf(candidate, type) ? candidate :
27277+
isTypeStrictSubtypeOf(candidate, type) ? candidate :
2727627278
isTypeAssignableTo(type, candidate) ? type :
2727727279
isTypeAssignableTo(candidate, type) ? candidate :
2727827280
getIntersectionType([type, candidate]);

0 commit comments

Comments
 (0)