diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2f020f46f22..76ab92544f4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15391,9 +15391,12 @@ namespace ts { } if (!targetType) { - const constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct); - targetType = constructSignatures && constructSignatures.length ? - getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature)))) : + let constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct); + if (constructSignatures.length === 0) { + constructSignatures = filter(getSignaturesOfType(rightType, SignatureKind.Call), sig => isJSConstructor(sig.declaration)); + } + targetType = constructSignatures.length ? + getUnionType(map(constructSignatures, signature => isJSConstructor(signature.declaration) && getJSClassType(getSymbolOfNode(signature.declaration!)) || getReturnTypeOfSignature(getErasedSignature(signature)))) : emptyObjectType; } diff --git a/tests/baselines/reference/controlFlowInstanceof.js b/tests/baselines/reference/controlFlowInstanceof.js deleted file mode 100644 index 1ac63f138f6..00000000000 --- a/tests/baselines/reference/controlFlowInstanceof.js +++ /dev/null @@ -1,196 +0,0 @@ -//// [controlFlowInstanceof.ts] -// Repros from #10167 - -function f1(s: Set | Set) { - s = new Set(); - s; // Set - if (s instanceof Set) { - s; // Set - } - s; // Set - s.add(42); -} - -function f2(s: Set | Set) { - s = new Set(); - s; // Set - if (s instanceof Promise) { - s; // Set & Promise - } - s; // Set - s.add(42); -} - -function f3(s: Set | Set) { - s; // Set | Set - if (s instanceof Set) { - s; // Set | Set - } - else { - s; // never - } -} - -function f4(s: Set | Set) { - s = new Set(); - s; // Set - if (s instanceof Set) { - s; // Set - } - else { - s; // never - } -} - -// More tests - -class A { a: string } -class B extends A { b: string } -class C extends A { c: string } - -function foo(x: A | undefined) { - x; // A | undefined - if (x instanceof B || x instanceof C) { - x; // B | C - } - x; // A | undefined - if (x instanceof B && x instanceof C) { - x; // B & C - } - x; // A | undefined - if (!x) { - return; - } - x; // A - if (x instanceof B) { - x; // B - if (x instanceof C) { - x; // B & C - } - else { - x; // B - } - x; // B - } - else { - x; // A - } - x; // A -} - -// X is neither assignable to Y nor a subtype of Y -// Y is assignable to X, but not a subtype of X - -interface X { - x?: string; -} - -class Y { - y: string; -} - -function goo(x: X) { - x; - if (x instanceof Y) { - x.y; - } - x; -} - -// Repro from #27282 - -declare const x: (() => void)|null; -declare const ctor: Function; - -if (x instanceof ctor) { - x(); -} - - -//// [controlFlowInstanceof.js] -// Repros from #10167 -function f1(s) { - s = new Set(); - s; // Set - if (s instanceof Set) { - s; // Set - } - s; // Set - s.add(42); -} -function f2(s) { - s = new Set(); - s; // Set - if (s instanceof Promise) { - s; // Set & Promise - } - s; // Set - s.add(42); -} -function f3(s) { - s; // Set | Set - if (s instanceof Set) { - s; // Set | Set - } - else { - s; // never - } -} -function f4(s) { - s = new Set(); - s; // Set - if (s instanceof Set) { - s; // Set - } - else { - s; // never - } -} -// More tests -class A { -} -class B extends A { -} -class C extends A { -} -function foo(x) { - x; // A | undefined - if (x instanceof B || x instanceof C) { - x; // B | C - } - x; // A | undefined - if (x instanceof B && x instanceof C) { - x; // B & C - } - x; // A | undefined - if (!x) { - return; - } - x; // A - if (x instanceof B) { - x; // B - if (x instanceof C) { - x; // B & C - } - else { - x; // B - } - x; // B - } - else { - x; // A - } - x; // A -} -class Y { -} -function goo(x) { - x; - if (x instanceof Y) { - x.y; - } - x; -} -if (x instanceof ctor) { - x(); -} diff --git a/tests/baselines/reference/controlFlowInstanceof.symbols b/tests/baselines/reference/controlFlowInstanceof.symbols index 72ab32d29d5..2be43d5ef6e 100644 --- a/tests/baselines/reference/controlFlowInstanceof.symbols +++ b/tests/baselines/reference/controlFlowInstanceof.symbols @@ -247,3 +247,28 @@ if (x instanceof ctor) { >x : Symbol(x, Decl(controlFlowInstanceof.ts, 100, 13)) } +// Repro from #27550 (based on uglify code) +=== tests/cases/compiler/uglify.js === +/** @constructor */ +function AtTop(val) { this.val = val } +>AtTop : Symbol(AtTop, Decl(uglify.js, 0, 0)) +>val : Symbol(val, Decl(uglify.js, 1, 15)) +>this.val : Symbol(AtTop.val, Decl(uglify.js, 1, 21)) +>this : Symbol(AtTop, Decl(uglify.js, 0, 0)) +>val : Symbol(AtTop.val, Decl(uglify.js, 1, 21)) +>val : Symbol(val, Decl(uglify.js, 1, 15)) + +/** @type {*} */ +var v = 1; +>v : Symbol(v, Decl(uglify.js, 3, 3)) + +if (v instanceof AtTop) { +>v : Symbol(v, Decl(uglify.js, 3, 3)) +>AtTop : Symbol(AtTop, Decl(uglify.js, 0, 0)) + + v.val +>v.val : Symbol(AtTop.val, Decl(uglify.js, 1, 21)) +>v : Symbol(v, Decl(uglify.js, 3, 3)) +>val : Symbol(AtTop.val, Decl(uglify.js, 1, 21)) +} + diff --git a/tests/baselines/reference/controlFlowInstanceof.types b/tests/baselines/reference/controlFlowInstanceof.types index e7c05a4c015..9aa38025a1c 100644 --- a/tests/baselines/reference/controlFlowInstanceof.types +++ b/tests/baselines/reference/controlFlowInstanceof.types @@ -261,3 +261,31 @@ if (x instanceof ctor) { >x : () => void } +// Repro from #27550 (based on uglify code) +=== tests/cases/compiler/uglify.js === +/** @constructor */ +function AtTop(val) { this.val = val } +>AtTop : typeof AtTop +>val : any +>this.val = val : any +>this.val : any +>this : AtTop +>val : any +>val : any + +/** @type {*} */ +var v = 1; +>v : any +>1 : 1 + +if (v instanceof AtTop) { +>v instanceof AtTop : boolean +>v : any +>AtTop : typeof AtTop + + v.val +>v.val : any +>v : AtTop +>val : any +} + diff --git a/tests/cases/compiler/controlFlowInstanceof.ts b/tests/cases/compiler/controlFlowInstanceof.ts index f9cf844572f..b032fb708dc 100644 --- a/tests/cases/compiler/controlFlowInstanceof.ts +++ b/tests/cases/compiler/controlFlowInstanceof.ts @@ -1,6 +1,10 @@ // @target: es6 +// @noEmit: true +// @allowJs: true +// @checkJs: true // @strictNullChecks: true +// @Filename: controlFlowInstanceof.ts // Repros from #10167 function f1(s: Set | Set) { @@ -107,3 +111,13 @@ declare const ctor: Function; if (x instanceof ctor) { x(); } + +// Repro from #27550 (based on uglify code) +// @Filename: uglify.js +/** @constructor */ +function AtTop(val) { this.val = val } +/** @type {*} */ +var v = 1; +if (v instanceof AtTop) { + v.val +}