diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 40db300d3103a..3dc9ee68d14a3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6362,9 +6362,10 @@ namespace ts { function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { // Check that type is not any, assumed result is true, and we have variable symbol on the left - if (isTypeAny(type) || !assumeTrue || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(expr.left) !== symbol) { + if (isTypeAny(type) || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(expr.left) !== symbol) { return type; } + // Check that right operand is a function type with a prototype property let rightType = checkExpression(expr.right); if (!isTypeSubtypeOf(rightType, globalFunctionType)) { @@ -6396,6 +6397,13 @@ namespace ts { } if (targetType) { + if (!assumeTrue) { + if (type.flags & TypeFlags.Union) { + return getUnionType(filter((type).types, t => !isTypeSubtypeOf(t, targetType))); + } + return type; + } + return getNarrowedType(type, targetType); } diff --git a/tests/baselines/reference/narrowTypeByInstanceof.types b/tests/baselines/reference/narrowTypeByInstanceof.types index e6a3466b88f5c..8bc13d12ca11c 100644 --- a/tests/baselines/reference/narrowTypeByInstanceof.types +++ b/tests/baselines/reference/narrowTypeByInstanceof.types @@ -63,7 +63,7 @@ if (elementA instanceof FileMatch && elementB instanceof FileMatch) { } else if (elementA instanceof Match && elementB instanceof Match) { >elementA instanceof Match && elementB instanceof Match : boolean >elementA instanceof Match : boolean ->elementA : FileMatch | Match +>elementA : Match | FileMatch >Match : typeof Match >elementB instanceof Match : boolean >elementB : FileMatch | Match diff --git a/tests/baselines/reference/typeGuardOfFormInstanceOf.js b/tests/baselines/reference/typeGuardOfFormInstanceOf.js index cab04365c1907..1431b4b9c6090 100644 --- a/tests/baselines/reference/typeGuardOfFormInstanceOf.js +++ b/tests/baselines/reference/typeGuardOfFormInstanceOf.js @@ -14,21 +14,58 @@ class C2 { class D1 extends C1 { p3: number; } +class C3 { + p4: number; +} var str: string; var num: number; var strOrNum: string | number; -var c1Orc2: C1 | C2; -str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 -num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 -str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 -num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 +var ctor1: C1 | C2; +str = ctor1 instanceof C1 && ctor1.p1; // C1 +num = ctor1 instanceof C2 && ctor1.p2; // C2 +str = ctor1 instanceof D1 && ctor1.p1; // D1 +num = ctor1 instanceof D1 && ctor1.p3; // D1 + +var ctor2: C2 | D1; +num = ctor2 instanceof C2 && ctor2.p2; // C2 +num = ctor2 instanceof D1 && ctor2.p3; // D1 +str = ctor2 instanceof D1 && ctor2.p1; // D1 +var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1 + +var ctor3: C1 | C2; +if (ctor3 instanceof C1) { + ctor3.p1; // C1 +} +else { + ctor3.p2; // C2 +} -var c2Ord1: C2 | D1; -num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 -num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 -str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 -var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 +var ctor4: C1 | C2 | C3; +if (ctor4 instanceof C1) { + ctor4.p1; // C1 +} +else if (ctor4 instanceof C2) { + ctor4.p2; // C2 +} +else { + ctor4.p4; // C3 +} + +var ctor5: C1 | D1 | C2; +if (ctor5 instanceof C1) { + ctor5.p1; // C1 +} +else { + ctor5.p2; // C2 +} + +var ctor6: C1 | C2 | C3; +if (ctor6 instanceof C1 || ctor6 instanceof C2) { +} +else { + ctor6.p4; // C3 +} //// [typeGuardOfFormInstanceOf.js] // A type guard of the form x instanceof C, where C is of a subtype of the global type 'Function' @@ -58,16 +95,51 @@ var D1 = (function (_super) { } return D1; })(C1); +var C3 = (function () { + function C3() { + } + return C3; +})(); var str; var num; var strOrNum; -var c1Orc2; -str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 -num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 -str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 -num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 -var c2Ord1; -num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 -num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 -str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 -var r2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 +var ctor1; +str = ctor1 instanceof C1 && ctor1.p1; // C1 +num = ctor1 instanceof C2 && ctor1.p2; // C2 +str = ctor1 instanceof D1 && ctor1.p1; // D1 +num = ctor1 instanceof D1 && ctor1.p3; // D1 +var ctor2; +num = ctor2 instanceof C2 && ctor2.p2; // C2 +num = ctor2 instanceof D1 && ctor2.p3; // D1 +str = ctor2 instanceof D1 && ctor2.p1; // D1 +var r2 = ctor2 instanceof C1 && ctor2; // C2 | D1 +var ctor3; +if (ctor3 instanceof C1) { + ctor3.p1; // C1 +} +else { + ctor3.p2; // C2 +} +var ctor4; +if (ctor4 instanceof C1) { + ctor4.p1; // C1 +} +else if (ctor4 instanceof C2) { + ctor4.p2; // C2 +} +else { + ctor4.p4; // C3 +} +var ctor5; +if (ctor5 instanceof C1) { + ctor5.p1; // C1 +} +else { + ctor5.p2; // C2 +} +var ctor6; +if (ctor6 instanceof C1 || ctor6 instanceof C2) { +} +else { + ctor6.p4; // C3 +} diff --git a/tests/baselines/reference/typeGuardOfFormInstanceOf.symbols b/tests/baselines/reference/typeGuardOfFormInstanceOf.symbols index 7a48d87e96392..0dd2844f6ad8c 100644 --- a/tests/baselines/reference/typeGuardOfFormInstanceOf.symbols +++ b/tests/baselines/reference/typeGuardOfFormInstanceOf.symbols @@ -24,86 +24,184 @@ class D1 extends C1 { p3: number; >p3 : Symbol(p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) } +class C3 { +>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1)) + + p4: number; +>p4 : Symbol(p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10)) +} var str: string; ->str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) +>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3)) var num: number; ->num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) +>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) var strOrNum: string | number; ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormInstanceOf.ts, 17, 3)) +>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormInstanceOf.ts, 20, 3)) -var c1Orc2: C1 | C2; ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +var ctor1: C1 | C2; +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) -str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 ->str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +str = ctor1 instanceof C1 && ctor1.p1; // C1 +>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) ->c1Orc2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) -num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 ->num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +num = ctor1 instanceof C2 && ctor1.p2; // C2 +>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) ->c1Orc2.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor1.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) -str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 ->str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +str = ctor1 instanceof D1 && ctor1.p1; // D1 +>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) ->c1Orc2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) -num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 ->num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +num = ctor1 instanceof D1 && ctor1.p3; // D1 +>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) ->c1Orc2.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) ->c1Orc2 : Symbol(c1Orc2, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor1.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) +>ctor1 : Symbol(ctor1, Decl(typeGuardOfFormInstanceOf.ts, 22, 3)) >p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) -var c2Ord1: C2 | D1; ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +var ctor2: C2 | D1; +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) -num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 ->num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +num = ctor2 instanceof C2 && ctor2.p2; // C2 +>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) ->c2Ord1.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +>ctor2.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) >p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) -num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 ->num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 16, 3)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +num = ctor2 instanceof D1 && ctor2.p3; // D1 +>num : Symbol(num, Decl(typeGuardOfFormInstanceOf.ts, 19, 3)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) ->c2Ord1.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +>ctor2.p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) >p3 : Symbol(D1.p3, Decl(typeGuardOfFormInstanceOf.ts, 12, 21)) -str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 ->str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 15, 3)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +str = ctor2 instanceof D1 && ctor2.p1; // D1 +>str : Symbol(str, Decl(typeGuardOfFormInstanceOf.ts, 18, 3)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) ->c2Ord1.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +>ctor2.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) >p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) -var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 ->r2 : Symbol(r2, Decl(typeGuardOfFormInstanceOf.ts, 29, 3)) +var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1 +>r2 : Symbol(r2, Decl(typeGuardOfFormInstanceOf.ts, 32, 3)) >D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) >C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) +>ctor2 : Symbol(ctor2, Decl(typeGuardOfFormInstanceOf.ts, 28, 3)) + +var ctor3: C1 | C2; +>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) +>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) + +if (ctor3 instanceof C1) { +>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) + + ctor3.p1; // C1 +>ctor3.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3)) +>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +} +else { + ctor3.p2; // C2 +>ctor3.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +>ctor3 : Symbol(ctor3, Decl(typeGuardOfFormInstanceOf.ts, 34, 3)) +>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +} + +var ctor4: C1 | C2 | C3; +>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) +>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) +>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1)) + +if (ctor4 instanceof C1) { +>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3)) >C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) ->c2Ord1 : Symbol(c2Ord1, Decl(typeGuardOfFormInstanceOf.ts, 25, 3)) + ctor4.p1; // C1 +>ctor4.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3)) +>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +} +else if (ctor4 instanceof C2) { +>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3)) +>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) + + ctor4.p2; // C2 +>ctor4.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3)) +>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +} +else { + ctor4.p4; // C3 +>ctor4.p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10)) +>ctor4 : Symbol(ctor4, Decl(typeGuardOfFormInstanceOf.ts, 42, 3)) +>p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10)) +} + +var ctor5: C1 | D1 | C2; +>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) +>D1 : Symbol(D1, Decl(typeGuardOfFormInstanceOf.ts, 11, 1)) +>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) + +if (ctor5 instanceof C1) { +>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) + + ctor5.p1; // C1 +>ctor5.p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3)) +>p1 : Symbol(C1.p1, Decl(typeGuardOfFormInstanceOf.ts, 6, 10)) +} +else { + ctor5.p2; // C2 +>ctor5.p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +>ctor5 : Symbol(ctor5, Decl(typeGuardOfFormInstanceOf.ts, 53, 3)) +>p2 : Symbol(C2.p2, Decl(typeGuardOfFormInstanceOf.ts, 9, 10)) +} + +var ctor6: C1 | C2 | C3; +>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) +>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) +>C3 : Symbol(C3, Decl(typeGuardOfFormInstanceOf.ts, 14, 1)) + +if (ctor6 instanceof C1 || ctor6 instanceof C2) { +>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3)) +>C1 : Symbol(C1, Decl(typeGuardOfFormInstanceOf.ts, 0, 0)) +>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3)) +>C2 : Symbol(C2, Decl(typeGuardOfFormInstanceOf.ts, 8, 1)) +} +else { + ctor6.p4; // C3 +>ctor6.p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10)) +>ctor6 : Symbol(ctor6, Decl(typeGuardOfFormInstanceOf.ts, 61, 3)) +>p4 : Symbol(C3.p4, Decl(typeGuardOfFormInstanceOf.ts, 15, 10)) +} diff --git a/tests/baselines/reference/typeGuardOfFormInstanceOf.types b/tests/baselines/reference/typeGuardOfFormInstanceOf.types index c824e907733f2..6b83b57dcb568 100644 --- a/tests/baselines/reference/typeGuardOfFormInstanceOf.types +++ b/tests/baselines/reference/typeGuardOfFormInstanceOf.types @@ -24,6 +24,12 @@ class D1 extends C1 { p3: number; >p3 : number } +class C3 { +>C3 : C3 + + p4: number; +>p4 : number +} var str: string; >str : string @@ -33,100 +39,199 @@ var num: number; var strOrNum: string | number; >strOrNum : string | number -var c1Orc2: C1 | C2; ->c1Orc2 : C1 | C2 +var ctor1: C1 | C2; +>ctor1 : C1 | C2 >C1 : C1 >C2 : C2 -str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 ->str = c1Orc2 instanceof C1 && c1Orc2.p1 : string +str = ctor1 instanceof C1 && ctor1.p1; // C1 +>str = ctor1 instanceof C1 && ctor1.p1 : string >str : string ->c1Orc2 instanceof C1 && c1Orc2.p1 : string ->c1Orc2 instanceof C1 : boolean ->c1Orc2 : C1 | C2 +>ctor1 instanceof C1 && ctor1.p1 : string +>ctor1 instanceof C1 : boolean +>ctor1 : C1 | C2 >C1 : typeof C1 ->c1Orc2.p1 : string ->c1Orc2 : C1 +>ctor1.p1 : string +>ctor1 : C1 >p1 : string -num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 ->num = c1Orc2 instanceof C2 && c1Orc2.p2 : number +num = ctor1 instanceof C2 && ctor1.p2; // C2 +>num = ctor1 instanceof C2 && ctor1.p2 : number >num : number ->c1Orc2 instanceof C2 && c1Orc2.p2 : number ->c1Orc2 instanceof C2 : boolean ->c1Orc2 : C1 | C2 +>ctor1 instanceof C2 && ctor1.p2 : number +>ctor1 instanceof C2 : boolean +>ctor1 : C1 | C2 >C2 : typeof C2 ->c1Orc2.p2 : number ->c1Orc2 : C2 +>ctor1.p2 : number +>ctor1 : C2 >p2 : number -str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 ->str = c1Orc2 instanceof D1 && c1Orc2.p1 : string +str = ctor1 instanceof D1 && ctor1.p1; // D1 +>str = ctor1 instanceof D1 && ctor1.p1 : string >str : string ->c1Orc2 instanceof D1 && c1Orc2.p1 : string ->c1Orc2 instanceof D1 : boolean ->c1Orc2 : C1 | C2 +>ctor1 instanceof D1 && ctor1.p1 : string +>ctor1 instanceof D1 : boolean +>ctor1 : C1 | C2 >D1 : typeof D1 ->c1Orc2.p1 : string ->c1Orc2 : D1 +>ctor1.p1 : string +>ctor1 : D1 >p1 : string -num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 ->num = c1Orc2 instanceof D1 && c1Orc2.p3 : number +num = ctor1 instanceof D1 && ctor1.p3; // D1 +>num = ctor1 instanceof D1 && ctor1.p3 : number >num : number ->c1Orc2 instanceof D1 && c1Orc2.p3 : number ->c1Orc2 instanceof D1 : boolean ->c1Orc2 : C1 | C2 +>ctor1 instanceof D1 && ctor1.p3 : number +>ctor1 instanceof D1 : boolean +>ctor1 : C1 | C2 >D1 : typeof D1 ->c1Orc2.p3 : number ->c1Orc2 : D1 +>ctor1.p3 : number +>ctor1 : D1 >p3 : number -var c2Ord1: C2 | D1; ->c2Ord1 : C2 | D1 +var ctor2: C2 | D1; +>ctor2 : C2 | D1 >C2 : C2 >D1 : D1 -num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 ->num = c2Ord1 instanceof C2 && c2Ord1.p2 : number +num = ctor2 instanceof C2 && ctor2.p2; // C2 +>num = ctor2 instanceof C2 && ctor2.p2 : number >num : number ->c2Ord1 instanceof C2 && c2Ord1.p2 : number ->c2Ord1 instanceof C2 : boolean ->c2Ord1 : C2 | D1 +>ctor2 instanceof C2 && ctor2.p2 : number +>ctor2 instanceof C2 : boolean +>ctor2 : C2 | D1 >C2 : typeof C2 ->c2Ord1.p2 : number ->c2Ord1 : C2 +>ctor2.p2 : number +>ctor2 : C2 >p2 : number -num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 ->num = c2Ord1 instanceof D1 && c2Ord1.p3 : number +num = ctor2 instanceof D1 && ctor2.p3; // D1 +>num = ctor2 instanceof D1 && ctor2.p3 : number >num : number ->c2Ord1 instanceof D1 && c2Ord1.p3 : number ->c2Ord1 instanceof D1 : boolean ->c2Ord1 : C2 | D1 +>ctor2 instanceof D1 && ctor2.p3 : number +>ctor2 instanceof D1 : boolean +>ctor2 : C2 | D1 >D1 : typeof D1 ->c2Ord1.p3 : number ->c2Ord1 : D1 +>ctor2.p3 : number +>ctor2 : D1 >p3 : number -str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 ->str = c2Ord1 instanceof D1 && c2Ord1.p1 : string +str = ctor2 instanceof D1 && ctor2.p1; // D1 +>str = ctor2 instanceof D1 && ctor2.p1 : string >str : string ->c2Ord1 instanceof D1 && c2Ord1.p1 : string ->c2Ord1 instanceof D1 : boolean ->c2Ord1 : C2 | D1 +>ctor2 instanceof D1 && ctor2.p1 : string +>ctor2 instanceof D1 : boolean +>ctor2 : C2 | D1 >D1 : typeof D1 ->c2Ord1.p1 : string ->c2Ord1 : D1 +>ctor2.p1 : string +>ctor2 : D1 >p1 : string -var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 +var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1 >r2 : D1 | C2 >D1 : D1 >C2 : C2 ->c2Ord1 instanceof C1 && c2Ord1 : D1 ->c2Ord1 instanceof C1 : boolean ->c2Ord1 : C2 | D1 +>ctor2 instanceof C1 && ctor2 : D1 +>ctor2 instanceof C1 : boolean +>ctor2 : C2 | D1 +>C1 : typeof C1 +>ctor2 : D1 + +var ctor3: C1 | C2; +>ctor3 : C1 | C2 +>C1 : C1 +>C2 : C2 + +if (ctor3 instanceof C1) { +>ctor3 instanceof C1 : boolean +>ctor3 : C1 | C2 +>C1 : typeof C1 + + ctor3.p1; // C1 +>ctor3.p1 : string +>ctor3 : C1 +>p1 : string +} +else { + ctor3.p2; // C2 +>ctor3.p2 : number +>ctor3 : C2 +>p2 : number +} + +var ctor4: C1 | C2 | C3; +>ctor4 : C1 | C2 | C3 +>C1 : C1 +>C2 : C2 +>C3 : C3 + +if (ctor4 instanceof C1) { +>ctor4 instanceof C1 : boolean +>ctor4 : C1 | C2 | C3 >C1 : typeof C1 ->c2Ord1 : D1 + ctor4.p1; // C1 +>ctor4.p1 : string +>ctor4 : C1 +>p1 : string +} +else if (ctor4 instanceof C2) { +>ctor4 instanceof C2 : boolean +>ctor4 : C2 | C3 +>C2 : typeof C2 + + ctor4.p2; // C2 +>ctor4.p2 : number +>ctor4 : C2 +>p2 : number +} +else { + ctor4.p4; // C3 +>ctor4.p4 : number +>ctor4 : C3 +>p4 : number +} + +var ctor5: C1 | D1 | C2; +>ctor5 : C1 | D1 | C2 +>C1 : C1 +>D1 : D1 +>C2 : C2 + +if (ctor5 instanceof C1) { +>ctor5 instanceof C1 : boolean +>ctor5 : C1 | D1 | C2 +>C1 : typeof C1 + + ctor5.p1; // C1 +>ctor5.p1 : string +>ctor5 : C1 +>p1 : string +} +else { + ctor5.p2; // C2 +>ctor5.p2 : number +>ctor5 : C2 +>p2 : number +} + +var ctor6: C1 | C2 | C3; +>ctor6 : C1 | C2 | C3 +>C1 : C1 +>C2 : C2 +>C3 : C3 + +if (ctor6 instanceof C1 || ctor6 instanceof C2) { +>ctor6 instanceof C1 || ctor6 instanceof C2 : boolean +>ctor6 instanceof C1 : boolean +>ctor6 : C1 | C2 | C3 +>C1 : typeof C1 +>ctor6 instanceof C2 : boolean +>ctor6 : C2 | C3 +>C2 : typeof C2 +} +else { + ctor6.p4; // C3 +>ctor6.p4 : number +>ctor6 : C3 +>p4 : number +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormInstanceOf.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormInstanceOf.ts index 233909f44aa5f..31514fca749d2 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormInstanceOf.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormInstanceOf.ts @@ -13,18 +13,55 @@ class C2 { class D1 extends C1 { p3: number; } +class C3 { + p4: number; +} var str: string; var num: number; var strOrNum: string | number; -var c1Orc2: C1 | C2; -str = c1Orc2 instanceof C1 && c1Orc2.p1; // C1 -num = c1Orc2 instanceof C2 && c1Orc2.p2; // C2 -str = c1Orc2 instanceof D1 && c1Orc2.p1; // D1 -num = c1Orc2 instanceof D1 && c1Orc2.p3; // D1 +var ctor1: C1 | C2; +str = ctor1 instanceof C1 && ctor1.p1; // C1 +num = ctor1 instanceof C2 && ctor1.p2; // C2 +str = ctor1 instanceof D1 && ctor1.p1; // D1 +num = ctor1 instanceof D1 && ctor1.p3; // D1 + +var ctor2: C2 | D1; +num = ctor2 instanceof C2 && ctor2.p2; // C2 +num = ctor2 instanceof D1 && ctor2.p3; // D1 +str = ctor2 instanceof D1 && ctor2.p1; // D1 +var r2: D1 | C2 = ctor2 instanceof C1 && ctor2; // C2 | D1 -var c2Ord1: C2 | D1; -num = c2Ord1 instanceof C2 && c2Ord1.p2; // C2 -num = c2Ord1 instanceof D1 && c2Ord1.p3; // D1 -str = c2Ord1 instanceof D1 && c2Ord1.p1; // D1 -var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1 \ No newline at end of file +var ctor3: C1 | C2; +if (ctor3 instanceof C1) { + ctor3.p1; // C1 +} +else { + ctor3.p2; // C2 +} + +var ctor4: C1 | C2 | C3; +if (ctor4 instanceof C1) { + ctor4.p1; // C1 +} +else if (ctor4 instanceof C2) { + ctor4.p2; // C2 +} +else { + ctor4.p4; // C3 +} + +var ctor5: C1 | D1 | C2; +if (ctor5 instanceof C1) { + ctor5.p1; // C1 +} +else { + ctor5.p2; // C2 +} + +var ctor6: C1 | C2 | C3; +if (ctor6 instanceof C1 || ctor6 instanceof C2) { +} +else { + ctor6.p4; // C3 +} \ No newline at end of file