From 157753520520fd0936bff280de30af56e15f94ee Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 26 Apr 2023 13:46:55 -0700 Subject: [PATCH] Fix callback return type annotation before constructor (#54034) --- src/compiler/checker.ts | 4 +- .../reference/callbackOnConstructor.js | 40 +++++++++++++++++++ .../reference/callbackOnConstructor.symbols | 24 +++++++++++ .../reference/callbackOnConstructor.types | 28 +++++++++++++ .../jsdoc/callbackOnConstructor.ts | 17 ++++++++ 5 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/callbackOnConstructor.js create mode 100644 tests/baselines/reference/callbackOnConstructor.symbols create mode 100644 tests/baselines/reference/callbackOnConstructor.types create mode 100644 tests/cases/conformance/jsdoc/callbackOnConstructor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cc906abfc21..869edfaffd4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14818,16 +14818,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (declaration.kind === SyntaxKind.Constructor) { return getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ClassDeclaration).symbol)); } + const typeNode = getEffectiveReturnTypeNode(declaration); if (isJSDocSignature(declaration)) { const root = getJSDocRoot(declaration); - if (root && isConstructorDeclaration(root.parent)) { + if (root && isConstructorDeclaration(root.parent) && !typeNode) { return getDeclaredTypeOfClassOrInterface(getMergedSymbol((root.parent.parent as ClassDeclaration).symbol)); } } if (isJSDocConstructSignature(declaration)) { return getTypeFromTypeNode((declaration.parameters[0] as ParameterDeclaration).type!); // TODO: GH#18217 } - const typeNode = getEffectiveReturnTypeNode(declaration); if (typeNode) { return getTypeFromTypeNode(typeNode); } diff --git a/tests/baselines/reference/callbackOnConstructor.js b/tests/baselines/reference/callbackOnConstructor.js new file mode 100644 index 00000000000..9f411596a99 --- /dev/null +++ b/tests/baselines/reference/callbackOnConstructor.js @@ -0,0 +1,40 @@ +//// [callbackOnConstructor.js] +export class Preferences { + assignability = "no" + /** + * @callback ValueGetter_2 + * @param {string} name + * @returns {boolean|number|string|undefined} + */ + constructor() {} +} + + +/** @type {ValueGetter_2} */ +var ooscope2 = s => s.length > 0 + + +//// [callbackOnConstructor.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Preferences = void 0; +var Preferences = /** @class */ (function () { + /** + * @callback ValueGetter_2 + * @param {string} name + * @returns {boolean|number|string|undefined} + */ + function Preferences() { + this.assignability = "no"; + } + return Preferences; +}()); +exports.Preferences = Preferences; +/** @type {ValueGetter_2} */ +var ooscope2 = function (s) { return s.length > 0; }; + + +//// [callbackOnConstructor.d.ts] +export class Preferences { + assignability: string; +} diff --git a/tests/baselines/reference/callbackOnConstructor.symbols b/tests/baselines/reference/callbackOnConstructor.symbols new file mode 100644 index 00000000000..688ef5911fd --- /dev/null +++ b/tests/baselines/reference/callbackOnConstructor.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/jsdoc/callbackOnConstructor.js === +export class Preferences { +>Preferences : Symbol(Preferences, Decl(callbackOnConstructor.js, 0, 0)) + + assignability = "no" +>assignability : Symbol(Preferences.assignability, Decl(callbackOnConstructor.js, 0, 26)) + + /** + * @callback ValueGetter_2 + * @param {string} name + * @returns {boolean|number|string|undefined} + */ + constructor() {} +} + + +/** @type {ValueGetter_2} */ +var ooscope2 = s => s.length > 0 +>ooscope2 : Symbol(ooscope2, Decl(callbackOnConstructor.js, 12, 3)) +>s : Symbol(s, Decl(callbackOnConstructor.js, 12, 14)) +>s.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>s : Symbol(s, Decl(callbackOnConstructor.js, 12, 14)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/callbackOnConstructor.types b/tests/baselines/reference/callbackOnConstructor.types new file mode 100644 index 00000000000..b3538e741c7 --- /dev/null +++ b/tests/baselines/reference/callbackOnConstructor.types @@ -0,0 +1,28 @@ +=== tests/cases/conformance/jsdoc/callbackOnConstructor.js === +export class Preferences { +>Preferences : Preferences + + assignability = "no" +>assignability : string +>"no" : "no" + + /** + * @callback ValueGetter_2 + * @param {string} name + * @returns {boolean|number|string|undefined} + */ + constructor() {} +} + + +/** @type {ValueGetter_2} */ +var ooscope2 = s => s.length > 0 +>ooscope2 : (name: string) => string | number | boolean +>s => s.length > 0 : (s: string) => string | number | boolean +>s : string +>s.length > 0 : boolean +>s.length : number +>s : string +>length : number +>0 : 0 + diff --git a/tests/cases/conformance/jsdoc/callbackOnConstructor.ts b/tests/cases/conformance/jsdoc/callbackOnConstructor.ts new file mode 100644 index 00000000000..6a99248d702 --- /dev/null +++ b/tests/cases/conformance/jsdoc/callbackOnConstructor.ts @@ -0,0 +1,17 @@ +// @filename: callbackOnConstructor.js +// @checkJs: true +// @outdir: dist +// @declaration: true +export class Preferences { + assignability = "no" + /** + * @callback ValueGetter_2 + * @param {string} name + * @returns {boolean|number|string|undefined} + */ + constructor() {} +} + + +/** @type {ValueGetter_2} */ +var ooscope2 = s => s.length > 0