diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2d5db22a565bf..30818837d0b17 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 0000000000000..3263a37a78076 --- /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 0000000000000..7c5767ded4a9b --- /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 0000000000000..5858ab1642203 --- /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 0000000000000..739c40efaceab --- /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')