Skip to content

Commit ac9b16c

Browse files
committed
refactor narrowTypeByInstanceof
1 parent 14362b0 commit ac9b16c

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

src/compiler/checker.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5384,38 +5384,42 @@ module ts {
53845384
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
53855385
return type;
53865386
}
5387-
// Target type is type of prototype property
5387+
5388+
let targetType: Type;
53885389
let prototypeProperty = getPropertyOfType(rightType, "prototype");
53895390
if (prototypeProperty) {
5390-
let targetType = getTypeOfSymbol(prototypeProperty);
5391-
if (targetType !== anyType) {
5392-
// Narrow to the target type if it's a subtype of the current type
5393-
if (isTypeSubtypeOf(targetType, type)) {
5394-
return targetType;
5395-
}
5396-
// If the current type is a union type, remove all constituents that aren't subtypes of the target.
5397-
if (type.flags & TypeFlags.Union) {
5398-
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, targetType)));
5399-
}
5391+
// Target type is type of the protoype property
5392+
let prototypePropertyType = getTypeOfSymbol(prototypeProperty);
5393+
if (prototypePropertyType !== anyType) {
5394+
targetType = prototypePropertyType;
54005395
}
54015396
}
5402-
// Target type is type of construct signature
5403-
let constructSignatures: Signature[];
5404-
if (rightType.flags & TypeFlags.Interface) {
5405-
constructSignatures = resolveDeclaredMembers(<InterfaceType>rightType).declaredConstructSignatures;
5406-
}
5407-
else if (rightType.flags & TypeFlags.Anonymous) {
5408-
constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct);
5397+
5398+
if (!targetType) {
5399+
// Target type is type of construct signature
5400+
let constructSignatures: Signature[];
5401+
if (rightType.flags & TypeFlags.Interface) {
5402+
constructSignatures = resolveDeclaredMembers(<InterfaceType>rightType).declaredConstructSignatures;
5403+
}
5404+
else if (rightType.flags & TypeFlags.Anonymous) {
5405+
constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct);
5406+
}
5407+
if (constructSignatures && constructSignatures.length) {
5408+
targetType = getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature))));
5409+
}
54095410
}
54105411

5411-
if (constructSignatures && constructSignatures.length !== 0) {
5412-
let instanceType = getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature))));
5413-
// Pickup type from union types
5412+
if (targetType) {
5413+
// Narrow to the target type if it's a subtype of the current type
5414+
if (isTypeSubtypeOf(targetType, type)) {
5415+
return targetType;
5416+
}
5417+
// If the current type is a union type, remove all constituents that aren't subtypes of the target.
54145418
if (type.flags & TypeFlags.Union) {
5415-
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, instanceType)));
5419+
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, targetType)));
54165420
}
5417-
return instanceType;
54185421
}
5422+
54195423
return type;
54205424
}
54215425

tests/baselines/reference/typeGuardsWithInstanceOfByConstructorSignature.errors.txt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(12,10): error TS2339: Property 'bar' does not exist on type 'A'.
22
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(33,5): error TS2322: Type 'string' is not assignable to type 'number'.
33
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(34,10): error TS2339: Property 'bar' does not exist on type 'B<number>'.
4-
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(63,10): error TS2339: Property 'bar2' does not exist on type 'C1'.
4+
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(62,10): error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
5+
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(63,10): error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
56
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(82,10): error TS2339: Property 'bar' does not exist on type 'D'.
6-
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(109,10): error TS2339: Property 'bar2' does not exist on type 'E1'.
7+
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(108,10): error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
8+
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(109,10): error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
79
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(131,11): error TS2339: Property 'foo' does not exist on type 'string | F'.
810
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(132,11): error TS2339: Property 'bar' does not exist on type 'string | F'.
911
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(157,11): error TS2339: Property 'foo2' does not exist on type 'G1'.
1012
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(179,11): error TS2339: Property 'bar' does not exist on type 'H'.
1113

1214

13-
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (10 errors) ====
15+
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (12 errors) ====
1416
interface AConstructor {
1517
new (): A;
1618
}
@@ -79,9 +81,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
7981
if (obj5 instanceof C) { // narrowed to C1.
8082
obj5.foo;
8183
obj5.bar1;
84+
~~~~
85+
!!! error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
8286
obj5.bar2;
8387
~~~~
84-
!!! error TS2339: Property 'bar2' does not exist on type 'C1'.
88+
!!! error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
8589
}
8690

8791
var obj6: any;
@@ -129,9 +133,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
129133
if (obj9 instanceof E) { // narrowed to E1.
130134
obj9.foo;
131135
obj9.bar1;
136+
~~~~
137+
!!! error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
132138
obj9.bar2;
133139
~~~~
134-
!!! error TS2339: Property 'bar2' does not exist on type 'E1'.
140+
!!! error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
135141
}
136142

137143
var obj10: any;

0 commit comments

Comments
 (0)