Skip to content

Commit e16bb3e

Browse files
authored
Improve behaviour of ... inside JSDoc functions (microsoft#22809)
* No error for ... on last param of jsdoc function * ... is a rest param w/array type in jsdoc function * Simplify getTypeFromJSDocVariadicType
1 parent ca1d19a commit e16bb3e

File tree

5 files changed

+78
-2
lines changed

5 files changed

+78
-2
lines changed

src/compiler/checker.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -24548,8 +24548,15 @@ namespace ts {
2454824548
checkJSDocTypeIsInJsFile(node);
2454924549
checkSourceElement(node.type);
2455024550

24551-
// Only legal location is in the *last* parameter tag.
24551+
// Only legal location is in the *last* parameter tag or last parameter of a JSDoc function.
2455224552
const { parent } = node;
24553+
if (isParameter(parent) && isJSDocFunctionType(parent.parent)) {
24554+
if (last(parent.parent.parameters) !== parent) {
24555+
error(node, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list);
24556+
}
24557+
return;
24558+
}
24559+
2455324560
if (!isJSDocTypeExpression(parent)) {
2455424561
error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature);
2455524562
}
@@ -24595,6 +24602,9 @@ namespace ts {
2459524602
}
2459624603
}
2459724604
}
24605+
if (isParameter(parent) && isJSDocFunctionType(parent.parent)) {
24606+
return createArrayType(type);
24607+
}
2459824608
return addOptionality(type);
2459924609
}
2460024610

src/compiler/utilities.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1861,7 +1861,7 @@ namespace ts {
18611861
}
18621862

18631863
export function isRestParameter(node: ParameterDeclaration): boolean {
1864-
return node.dotDotDotToken !== undefined;
1864+
return node.dotDotDotToken !== undefined || node.type && node.type.kind === SyntaxKind.JSDocVariadicType;
18651865
}
18661866

18671867
export const enum AssignmentKind {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/conformance/jsdoc/a.js ===
2+
// from bcryptjs
3+
/** @param {function(...[*])} callback */
4+
function g(callback) {
5+
>g : Symbol(g, Decl(a.js, 0, 0))
6+
>callback : Symbol(callback, Decl(a.js, 2, 11))
7+
8+
callback([1], [2], [3])
9+
>callback : Symbol(callback, Decl(a.js, 2, 11))
10+
}
11+
12+
/**
13+
* @type {!function(...number):string}
14+
* @inner
15+
*/
16+
var stringFromCharCode = String.fromCharCode;
17+
>stringFromCharCode : Symbol(stringFromCharCode, Decl(a.js, 10, 3))
18+
>String.fromCharCode : Symbol(StringConstructor.fromCharCode, Decl(lib.d.ts, --, --))
19+
>String : Symbol(String, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
20+
>fromCharCode : Symbol(StringConstructor.fromCharCode, Decl(lib.d.ts, --, --))
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
=== tests/cases/conformance/jsdoc/a.js ===
2+
// from bcryptjs
3+
/** @param {function(...[*])} callback */
4+
function g(callback) {
5+
>g : (callback: (...arg0: [any][]) => any) => void
6+
>callback : (...arg0: [any][]) => any
7+
8+
callback([1], [2], [3])
9+
>callback([1], [2], [3]) : any
10+
>callback : (...arg0: [any][]) => any
11+
>[1] : [number]
12+
>1 : 1
13+
>[2] : [number]
14+
>2 : 2
15+
>[3] : [number]
16+
>3 : 3
17+
}
18+
19+
/**
20+
* @type {!function(...number):string}
21+
* @inner
22+
*/
23+
var stringFromCharCode = String.fromCharCode;
24+
>stringFromCharCode : (...arg0: number[]) => string
25+
>String.fromCharCode : (...codes: number[]) => string
26+
>String : StringConstructor
27+
>fromCharCode : (...codes: number[]) => string
28+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @noEmit: true
2+
// @allowJs: true
3+
// @checkJs: true
4+
// @strict: true
5+
// @Filename: a.js
6+
7+
// from bcryptjs
8+
/** @param {function(...[*])} callback */
9+
function g(callback) {
10+
callback([1], [2], [3])
11+
}
12+
13+
/**
14+
* @type {!function(...number):string}
15+
* @inner
16+
*/
17+
var stringFromCharCode = String.fromCharCode;

0 commit comments

Comments
 (0)