From f5a45f614b81cb4030738725371f841fd29bb05e Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Tue, 11 Apr 2023 23:03:36 +0300 Subject: [PATCH 1/2] fix(53722): resolve constructor type parameters from the parent class --- src/compiler/checker.ts | 10 ++++-- .../baselines/reference/overloadTag3.symbols | 29 +++++++++++++++++ tests/baselines/reference/overloadTag3.types | 31 +++++++++++++++++++ tests/cases/conformance/jsdoc/overloadTag3.ts | 24 ++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/overloadTag3.symbols create mode 100644 tests/baselines/reference/overloadTag3.types create mode 100644 tests/cases/conformance/jsdoc/overloadTag3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6b152ad909dcb..b0162249b4395 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14541,9 +14541,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - const classType = declaration.kind === SyntaxKind.Constructor ? - getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ClassDeclaration).symbol)) - : undefined; + const constructorDeclaration = tryGetConstructorDeclaration(declaration); + const classType = constructorDeclaration ? getDeclaredTypeOfClassOrInterface(getMergedSymbol((constructorDeclaration.parent as ClassDeclaration).symbol)) : undefined; const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); if (hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) { flags |= SignatureFlags.HasRestParameter; @@ -14559,6 +14558,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.resolvedSignature; } + function tryGetConstructorDeclaration(declaration: SignatureDeclaration | JSDocSignature) { + const node = isJSDocSignature(declaration) ? getEffectiveJSDocHost(declaration) : declaration; + return node && isConstructorDeclaration(node) ? node : undefined; + } + /** * A JS function gets a synthetic rest parameter if it references `arguments` AND: * 1. It has no parameters but at least one `@param` with a type that starts with `...` diff --git a/tests/baselines/reference/overloadTag3.symbols b/tests/baselines/reference/overloadTag3.symbols new file mode 100644 index 0000000000000..4c59ed907f698 --- /dev/null +++ b/tests/baselines/reference/overloadTag3.symbols @@ -0,0 +1,29 @@ +=== /a.js === +/** + * @template T + */ +export class Foo { +>Foo : Symbol(Foo, Decl(a.js, 0, 0)) + + /** + * @constructor + * @overload + */ + constructor() { } + + /** + * @param {T} value + */ + bar(value) { } +>bar : Symbol(Foo.bar, Decl(a.js, 8, 21)) +>value : Symbol(value, Decl(a.js, 13, 8)) +} + +/** @type {Foo} */ +let foo; +>foo : Symbol(foo, Decl(a.js, 17, 3)) + +foo = new Foo(); +>foo : Symbol(foo, Decl(a.js, 17, 3)) +>Foo : Symbol(Foo, Decl(a.js, 0, 0)) + diff --git a/tests/baselines/reference/overloadTag3.types b/tests/baselines/reference/overloadTag3.types new file mode 100644 index 0000000000000..8ff42674a85e7 --- /dev/null +++ b/tests/baselines/reference/overloadTag3.types @@ -0,0 +1,31 @@ +=== /a.js === +/** + * @template T + */ +export class Foo { +>Foo : Foo + + /** + * @constructor + * @overload + */ + constructor() { } + + /** + * @param {T} value + */ + bar(value) { } +>bar : (value: T) => void +>value : T +} + +/** @type {Foo} */ +let foo; +>foo : Foo + +foo = new Foo(); +>foo = new Foo() : Foo +>foo : Foo +>new Foo() : Foo +>Foo : typeof Foo + diff --git a/tests/cases/conformance/jsdoc/overloadTag3.ts b/tests/cases/conformance/jsdoc/overloadTag3.ts new file mode 100644 index 0000000000000..999184d4263e2 --- /dev/null +++ b/tests/cases/conformance/jsdoc/overloadTag3.ts @@ -0,0 +1,24 @@ +// @checkJs: true +// @allowJs: true +// @strict: true +// @noEmit: true +// @filename: /a.js +/** + * @template T + */ +export class Foo { + /** + * @constructor + * @overload + */ + constructor() { } + + /** + * @param {T} value + */ + bar(value) { } +} + +/** @type {Foo} */ +let foo; +foo = new Foo(); From 537f9c3a1065697bd4899b4ab7a37e993896a747 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Fri, 14 Apr 2023 05:18:32 +0300 Subject: [PATCH 2/2] change formatting --- src/compiler/checker.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b0162249b4395..6be419174bdf1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14541,8 +14541,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - const constructorDeclaration = tryGetConstructorDeclaration(declaration); - const classType = constructorDeclaration ? getDeclaredTypeOfClassOrInterface(getMergedSymbol((constructorDeclaration.parent as ClassDeclaration).symbol)) : undefined; + const hostDeclaration = isJSDocSignature(declaration) ? getEffectiveJSDocHost(declaration) : declaration; + const classType = hostDeclaration && isConstructorDeclaration(hostDeclaration) ? + getDeclaredTypeOfClassOrInterface(getMergedSymbol((hostDeclaration.parent as ClassDeclaration).symbol)) + : undefined; const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); if (hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) { flags |= SignatureFlags.HasRestParameter; @@ -14558,11 +14560,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.resolvedSignature; } - function tryGetConstructorDeclaration(declaration: SignatureDeclaration | JSDocSignature) { - const node = isJSDocSignature(declaration) ? getEffectiveJSDocHost(declaration) : declaration; - return node && isConstructorDeclaration(node) ? node : undefined; - } - /** * A JS function gets a synthetic rest parameter if it references `arguments` AND: * 1. It has no parameters but at least one `@param` with a type that starts with `...`