Skip to content

Commit 8c6b858

Browse files
authored
Properly handle rest parameters in function declarations with @type annotations (microsoft#39473)
* Properly handle rest parameters in function declarations with @type annotations * Add tests
1 parent d2b32b4 commit 8c6b858

File tree

5 files changed

+72
-1
lines changed

5 files changed

+72
-1
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7803,7 +7803,9 @@ namespace ts {
78037803
if (isInJSFile(declaration)) {
78047804
const typeTag = getJSDocType(func);
78057805
if (typeTag && isFunctionTypeNode(typeTag)) {
7806-
return getTypeAtPosition(getSignatureFromDeclaration(typeTag), func.parameters.indexOf(declaration));
7806+
const signature = getSignatureFromDeclaration(typeTag);
7807+
const pos = func.parameters.indexOf(declaration);
7808+
return declaration.dotDotDotToken ? getRestTypeAtPosition(signature, pos) : getTypeAtPosition(signature, pos);
78077809
}
78087810
}
78097811
// Use contextual parameter type if one is available

tests/baselines/reference/jsdocFunctionType.errors.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,16 @@ tests/cases/conformance/jsdoc/functions.js(65,14): error TS2345: Argument of typ
7272
!!! error TS2345: Argument of type 'typeof E' is not assignable to parameter of type 'new (arg1: number) => { length: number; }'.
7373
!!! error TS2345: Property 'length' is missing in type 'E' but required in type '{ length: number; }'.
7474
!!! related TS2728 tests/cases/conformance/jsdoc/functions.js:12:28: 'length' is declared here.
75+
76+
// Repro from #39229
77+
78+
/**
79+
* @type {(...args: [string, string] | [number, string, string]) => void}
80+
*/
81+
function foo(...args) {
82+
args;
83+
}
84+
85+
foo('abc', 'def');
86+
foo(42, 'abc', 'def');
7587

tests/baselines/reference/jsdocFunctionType.symbols

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,22 @@ var y3 = id2(E);
141141
>id2 : Symbol(id2, Decl(functions.js, 8, 53))
142142
>E : Symbol(E, Decl(functions.js, 59, 3))
143143

144+
// Repro from #39229
145+
146+
/**
147+
* @type {(...args: [string, string] | [number, string, string]) => void}
148+
*/
149+
function foo(...args) {
150+
>foo : Symbol(foo, Decl(functions.js, 64, 16))
151+
>args : Symbol(args, Decl(functions.js, 71, 13))
152+
153+
args;
154+
>args : Symbol(args, Decl(functions.js, 71, 13))
155+
}
156+
157+
foo('abc', 'def');
158+
>foo : Symbol(foo, Decl(functions.js, 64, 16))
159+
160+
foo(42, 'abc', 'def');
161+
>foo : Symbol(foo, Decl(functions.js, 64, 16))
162+

tests/baselines/reference/jsdocFunctionType.types

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,29 @@ var y3 = id2(E);
165165
>id2 : (c: new (arg1: number) => { length: number; }) => new (arg1: number) => { length: number; }
166166
>E : typeof E
167167

168+
// Repro from #39229
169+
170+
/**
171+
* @type {(...args: [string, string] | [number, string, string]) => void}
172+
*/
173+
function foo(...args) {
174+
>foo : (...args: [string, string] | [number, string, string]) => void
175+
>args : [string, string] | [number, string, string]
176+
177+
args;
178+
>args : [string, string] | [number, string, string]
179+
}
180+
181+
foo('abc', 'def');
182+
>foo('abc', 'def') : void
183+
>foo : (...args: [string, string] | [number, string, string]) => void
184+
>'abc' : "abc"
185+
>'def' : "def"
186+
187+
foo(42, 'abc', 'def');
188+
>foo(42, 'abc', 'def') : void
189+
>foo : (...args: [string, string] | [number, string, string]) => void
190+
>42 : 42
191+
>'abc' : "abc"
192+
>'def' : "def"
193+

tests/cases/conformance/jsdoc/jsdocFunctionType.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,15 @@ var E = function(n) {
7070

7171

7272
var y3 = id2(E);
73+
74+
// Repro from #39229
75+
76+
/**
77+
* @type {(...args: [string, string] | [number, string, string]) => void}
78+
*/
79+
function foo(...args) {
80+
args;
81+
}
82+
83+
foo('abc', 'def');
84+
foo(42, 'abc', 'def');

0 commit comments

Comments
 (0)