@@ -5919,6 +5919,13 @@ namespace ts {
5919
return isTypeRelatedTo(source, target, assignableRelation);
5919
return isTypeRelatedTo(source, target, assignableRelation);
5920
}
5920
}
5921
5921
5922
+ // A type S is considered to be an instance of a type T if S and T are the same type or if S is a
5923
+ // subtype of T but not structurally identical to T. This specifically means that two distinct but
5924
+ // structurally identical types (such as two classes) are not considered instances of each other.
5925
+ function isTypeInstanceOf(source: Type, target: Type): boolean {
5926
+ return source === target || isTypeSubtypeOf(source, target) && !isTypeIdenticalTo(source, target);
5927
+ }
5928
+
5922
/**
5929
/**
5923
* This is *not* a bi-directional relationship.
5930
* This is *not* a bi-directional relationship.
5924
* If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'.
5931
* If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'.
@@ -8569,17 +8576,13 @@ namespace ts {
8569
}
8576
}
8570
8577
8571
function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean) {
8578
function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean) {
8572
- // In the false branch we keep types that aren't subtypes of the candidate type and we keep structurally
8573
- // identical types except for the current type itself. The latter rule means that given two structurally
8574
- // identical classes A and B and a variable x of type A, in the false branch of an 'x instanceof B' type
8575
- // guard x keeps type A and is not narrowed to type never.
8576
if (!assumeTrue) {
8579
if (!assumeTrue) {
8577
- return filterType(type, t => !isTypeSubtypeOf (t, candidate) || isTypeIdenticalTo(t, candidate) && t !== candidate );
8580
+ return filterType(type, t => !isTypeInstanceOf (t, candidate));
8578
}
8581
}
8579
- // If the current type is a union type, remove all constituents that aren 't assignable to
8582
+ // If the current type is a union type, remove all constituents that couldn 't be instances of
8580
// the candidate type. If one or more constituents remain, return a union of those.
8583
// the candidate type. If one or more constituents remain, return a union of those.
8581
if (type.flags & TypeFlags.Union) {
8584
if (type.flags & TypeFlags.Union) {
8582
- const assignableConstituents = filter((<UnionType>type).types, t => isTypeAssignableTo (t, candidate));
8585
+ const assignableConstituents = filter((<UnionType>type).types, t => isTypeInstanceOf (t, candidate));
8583
if (assignableConstituents.length) {
8586
if (assignableConstituents.length) {
8584
return getUnionType(assignableConstituents);
8587
return getUnionType(assignableConstituents);
8585
}
8588
}
0 commit comments