diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 267da5727370b..29a555ee29705 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24548,8 +24548,15 @@ namespace ts { checkJSDocTypeIsInJsFile(node); checkSourceElement(node.type); - // Only legal location is in the *last* parameter tag. + // Only legal location is in the *last* parameter tag or last parameter of a JSDoc function. const { parent } = node; + if (isParameter(parent) && isJSDocFunctionType(parent.parent)) { + if (last(parent.parent.parameters) !== parent) { + error(node, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); + } + return; + } + if (!isJSDocTypeExpression(parent)) { error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature); } @@ -24595,6 +24602,9 @@ namespace ts { } } } + if (isParameter(parent) && isJSDocFunctionType(parent.parent)) { + return createArrayType(type); + } return addOptionality(type); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 236177ea6ff4d..c686dbcee540d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1861,7 +1861,7 @@ namespace ts { } export function isRestParameter(node: ParameterDeclaration): boolean { - return node.dotDotDotToken !== undefined; + return node.dotDotDotToken !== undefined || node.type && node.type.kind === SyntaxKind.JSDocVariadicType; } export const enum AssignmentKind { diff --git a/tests/baselines/reference/jsdocParseDotDotDotInJSDocFunction.symbols b/tests/baselines/reference/jsdocParseDotDotDotInJSDocFunction.symbols new file mode 100644 index 0000000000000..a5737c7b245f6 --- /dev/null +++ b/tests/baselines/reference/jsdocParseDotDotDotInJSDocFunction.symbols @@ -0,0 +1,21 @@ +=== tests/cases/conformance/jsdoc/a.js === +// from bcryptjs +/** @param {function(...[*])} callback */ +function g(callback) { +>g : Symbol(g, Decl(a.js, 0, 0)) +>callback : Symbol(callback, Decl(a.js, 2, 11)) + + callback([1], [2], [3]) +>callback : Symbol(callback, Decl(a.js, 2, 11)) +} + +/** + * @type {!function(...number):string} + * @inner + */ +var stringFromCharCode = String.fromCharCode; +>stringFromCharCode : Symbol(stringFromCharCode, Decl(a.js, 10, 3)) +>String.fromCharCode : Symbol(StringConstructor.fromCharCode, Decl(lib.d.ts, --, --)) +>String : Symbol(String, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>fromCharCode : Symbol(StringConstructor.fromCharCode, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/jsdocParseDotDotDotInJSDocFunction.types b/tests/baselines/reference/jsdocParseDotDotDotInJSDocFunction.types new file mode 100644 index 0000000000000..3c3bff9169fdc --- /dev/null +++ b/tests/baselines/reference/jsdocParseDotDotDotInJSDocFunction.types @@ -0,0 +1,28 @@ +=== tests/cases/conformance/jsdoc/a.js === +// from bcryptjs +/** @param {function(...[*])} callback */ +function g(callback) { +>g : (callback: (...arg0: [any][]) => any) => void +>callback : (...arg0: [any][]) => any + + callback([1], [2], [3]) +>callback([1], [2], [3]) : any +>callback : (...arg0: [any][]) => any +>[1] : [number] +>1 : 1 +>[2] : [number] +>2 : 2 +>[3] : [number] +>3 : 3 +} + +/** + * @type {!function(...number):string} + * @inner + */ +var stringFromCharCode = String.fromCharCode; +>stringFromCharCode : (...arg0: number[]) => string +>String.fromCharCode : (...codes: number[]) => string +>String : StringConstructor +>fromCharCode : (...codes: number[]) => string + diff --git a/tests/cases/conformance/jsdoc/jsdocParseDotDotDotInJSDocFunction.ts b/tests/cases/conformance/jsdoc/jsdocParseDotDotDotInJSDocFunction.ts new file mode 100644 index 0000000000000..7c34bfc672d2f --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocParseDotDotDotInJSDocFunction.ts @@ -0,0 +1,17 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @strict: true +// @Filename: a.js + +// from bcryptjs +/** @param {function(...[*])} callback */ +function g(callback) { + callback([1], [2], [3]) +} + +/** + * @type {!function(...number):string} + * @inner + */ +var stringFromCharCode = String.fromCharCode;