From 080e41dc90eef45522a83874cb67cb52838ca596 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 28 Oct 2019 10:14:04 -0700 Subject: [PATCH] Fix type reference to merged prototype property assignment (#34764) The constructor function code path in the return type checking of signatures needs to pass the *merged* symbol of the declaration to getDeclaredTypeOfClassOrInterface. Other callers of getDeclaredTypeOfClassOrInterface do this, or used an already-merged symbol. Fixes #33993 --- src/compiler/checker.ts | 4 +-- ...pertyAssignmentMergedTypeReference.symbols | 20 ++++++++++++++ ...ropertyAssignmentMergedTypeReference.types | 26 +++++++++++++++++++ ...pePropertyAssignmentMergedTypeReference.ts | 14 ++++++++++ 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.symbols create mode 100644 tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.types create mode 100644 tests/cases/conformance/salsa/prototypePropertyAssignmentMergedTypeReference.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 69f4983ca72..c8df4873377 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13962,13 +13962,13 @@ namespace ts { // If a signature resolution is already in-flight, skip issuing a circularity error // here and just use the `any` type directly const targetReturnType = isResolvingReturnTypeOfSignature(target) ? anyType - : target.declaration && isJSConstructor(target.declaration) ? getDeclaredTypeOfClassOrInterface(target.declaration.symbol) + : target.declaration && isJSConstructor(target.declaration) ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(target.declaration.symbol)) : getReturnTypeOfSignature(target); if (targetReturnType === voidType) { return result; } const sourceReturnType = isResolvingReturnTypeOfSignature(source) ? anyType - : source.declaration && isJSConstructor(source.declaration) ? getDeclaredTypeOfClassOrInterface(source.declaration.symbol) + : source.declaration && isJSConstructor(source.declaration) ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(source.declaration.symbol)) : getReturnTypeOfSignature(source); // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions diff --git a/tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.symbols b/tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.symbols new file mode 100644 index 00000000000..7e3f503c7bc --- /dev/null +++ b/tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.symbols @@ -0,0 +1,20 @@ +=== tests/cases/conformance/salsa/prototypePropertyAssignmentMergedTypeReference.js === +// https://github.com/microsoft/TypeScript/issues/33993 +var f = function() { +>f : Symbol(f, Decl(prototypePropertyAssignmentMergedTypeReference.js, 1, 3)) + + return 12; +}; + +f.prototype.a = "a"; +>f.prototype : Symbol(f.a, Decl(prototypePropertyAssignmentMergedTypeReference.js, 3, 2)) +>f : Symbol(f, Decl(prototypePropertyAssignmentMergedTypeReference.js, 1, 3)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(f.a, Decl(prototypePropertyAssignmentMergedTypeReference.js, 3, 2)) + +/** @type {new () => f} */ +var x = f; +>x : Symbol(x, Decl(prototypePropertyAssignmentMergedTypeReference.js, 8, 3)) +>f : Symbol(f, Decl(prototypePropertyAssignmentMergedTypeReference.js, 1, 3)) + + diff --git a/tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.types b/tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.types new file mode 100644 index 00000000000..2fa4bcee43b --- /dev/null +++ b/tests/baselines/reference/prototypePropertyAssignmentMergedTypeReference.types @@ -0,0 +1,26 @@ +=== tests/cases/conformance/salsa/prototypePropertyAssignmentMergedTypeReference.js === +// https://github.com/microsoft/TypeScript/issues/33993 +var f = function() { +>f : typeof f +>function() { return 12;} : typeof f + + return 12; +>12 : 12 + +}; + +f.prototype.a = "a"; +>f.prototype.a = "a" : "a" +>f.prototype.a : any +>f.prototype : any +>f : typeof f +>prototype : any +>a : any +>"a" : "a" + +/** @type {new () => f} */ +var x = f; +>x : new () => f +>f : typeof f + + diff --git a/tests/cases/conformance/salsa/prototypePropertyAssignmentMergedTypeReference.ts b/tests/cases/conformance/salsa/prototypePropertyAssignmentMergedTypeReference.ts new file mode 100644 index 00000000000..f79b9e01b5f --- /dev/null +++ b/tests/cases/conformance/salsa/prototypePropertyAssignmentMergedTypeReference.ts @@ -0,0 +1,14 @@ +// https://github.com/microsoft/TypeScript/issues/33993 +// @noEmit: true +// @allowJs: true +// @checkJS: true +// @filename: prototypePropertyAssignmentMergedTypeReference.js +var f = function() { + return 12; +}; + +f.prototype.a = "a"; + +/** @type {new () => f} */ +var x = f; +