From 2bb54dc11a8938bdc2e71aa369f6f6d9ac718af8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 7 Apr 2021 08:12:05 -0700 Subject: [PATCH] Fix getTypeFromJSDocVariadicType in callback tag (#43562) * Fix getTypeFromJSDocVariadicType in @callback Variadics have never worked there, I think. * add test + fix lint * remove outdated comment --- src/compiler/checker.ts | 7 ++-- .../reference/callbackTagVariadicType.js | 36 +++++++++++++++++++ .../reference/callbackTagVariadicType.symbols | 15 ++++++++ .../reference/callbackTagVariadicType.types | 20 +++++++++++ .../jsdoc/callbackTagVariadicType.ts | 14 ++++++++ 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/callbackTagVariadicType.js create mode 100644 tests/baselines/reference/callbackTagVariadicType.symbols create mode 100644 tests/baselines/reference/callbackTagVariadicType.types create mode 100644 tests/cases/conformance/jsdoc/callbackTagVariadicType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2d5db22a565..30818837d0b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -38433,7 +38433,8 @@ namespace ts { if (isJSDocTypeExpression(node.parent) && isJSDocParameterTag(paramTag)) { // Else we will add a diagnostic, see `checkJSDocVariadicType`. const host = getHostSignatureFromJSDoc(paramTag); - if (host) { + const isCallbackTag = isJSDocCallbackTag(paramTag.parent.parent); + if (host || isCallbackTag) { /* Only return an array type if the corresponding parameter is marked as a rest parameter, or if there are no parameters. So in the following situation we will not create an array type: @@ -38441,7 +38442,9 @@ namespace ts { function f(a) {} Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type. */ - const lastParamDeclaration = lastOrUndefined(host.parameters); + const lastParamDeclaration = isCallbackTag + ? lastOrUndefined((paramTag.parent.parent as unknown as JSDocCallbackTag).typeExpression.parameters) + : lastOrUndefined(host!.parameters); const symbol = getParameterSymbolFromJSDoc(paramTag); if (!lastParamDeclaration || symbol && lastParamDeclaration.symbol === symbol && isRestParameter(lastParamDeclaration)) { diff --git a/tests/baselines/reference/callbackTagVariadicType.js b/tests/baselines/reference/callbackTagVariadicType.js new file mode 100644 index 00000000000..3263a37a780 --- /dev/null +++ b/tests/baselines/reference/callbackTagVariadicType.js @@ -0,0 +1,36 @@ +//// [callbackTagVariadicType.js] +/** + * @callback Foo + * @param {...string} args + * @returns {number} + */ + +/** @type {Foo} */ +export const x = () => 1 +var res = x('a', 'b') + + +//// [callbackTagVariadicType.js] +"use strict"; +/** + * @callback Foo + * @param {...string} args + * @returns {number} + */ +exports.__esModule = true; +exports.x = void 0; +/** @type {Foo} */ +var x = function () { return 1; }; +exports.x = x; +var res = (0, exports.x)('a', 'b'); + + +//// [callbackTagVariadicType.d.ts] +/** + * @callback Foo + * @param {...string} args + * @returns {number} + */ +/** @type {Foo} */ +export const x: Foo; +export type Foo = (...args: string[]) => number; diff --git a/tests/baselines/reference/callbackTagVariadicType.symbols b/tests/baselines/reference/callbackTagVariadicType.symbols new file mode 100644 index 00000000000..7c5767ded4a --- /dev/null +++ b/tests/baselines/reference/callbackTagVariadicType.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/jsdoc/callbackTagVariadicType.js === +/** + * @callback Foo + * @param {...string} args + * @returns {number} + */ + +/** @type {Foo} */ +export const x = () => 1 +>x : Symbol(x, Decl(callbackTagVariadicType.js, 7, 12)) + +var res = x('a', 'b') +>res : Symbol(res, Decl(callbackTagVariadicType.js, 8, 3)) +>x : Symbol(x, Decl(callbackTagVariadicType.js, 7, 12)) + diff --git a/tests/baselines/reference/callbackTagVariadicType.types b/tests/baselines/reference/callbackTagVariadicType.types new file mode 100644 index 00000000000..5858ab16422 --- /dev/null +++ b/tests/baselines/reference/callbackTagVariadicType.types @@ -0,0 +1,20 @@ +=== tests/cases/conformance/jsdoc/callbackTagVariadicType.js === +/** + * @callback Foo + * @param {...string} args + * @returns {number} + */ + +/** @type {Foo} */ +export const x = () => 1 +>x : Foo +>() => 1 : () => number +>1 : 1 + +var res = x('a', 'b') +>res : number +>x('a', 'b') : number +>x : Foo +>'a' : "a" +>'b' : "b" + diff --git a/tests/cases/conformance/jsdoc/callbackTagVariadicType.ts b/tests/cases/conformance/jsdoc/callbackTagVariadicType.ts new file mode 100644 index 00000000000..739c40eface --- /dev/null +++ b/tests/cases/conformance/jsdoc/callbackTagVariadicType.ts @@ -0,0 +1,14 @@ +// @declaration: true +// @outDir: bin/ +// @checkJs: true +// @Filename: callbackTagVariadicType.js + +/** + * @callback Foo + * @param {...string} args + * @returns {number} + */ + +/** @type {Foo} */ +export const x = () => 1 +var res = x('a', 'b')