Skip to content

Commit 970be9f

Browse files
committed
Support rest parameters in function signatures
1 parent f2193db commit 970be9f

File tree

4 files changed

+50
-9
lines changed

4 files changed

+50
-9
lines changed

src/utils/__tests__/getFlowType-test.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ describe('getFlowType', () => {
216216
});
217217

218218
it('detects function signature type', () => {
219-
const typePath = expression('x: (p1: number, p2: ?string) => boolean')
219+
const typePath = expression(
220+
'x: (p1: number, p2: ?string, ...rest: Array<string>) => boolean',
221+
)
220222
.get('typeAnnotation')
221223
.get('typeAnnotation');
222224
expect(getFlowType(typePath)).toEqual({
@@ -226,10 +228,18 @@ describe('getFlowType', () => {
226228
arguments: [
227229
{ name: 'p1', type: { name: 'number' } },
228230
{ name: 'p2', type: { name: 'string', nullable: true } },
231+
{
232+
name: 'rest',
233+
type: {
234+
name: 'Array',
235+
elements: [{ name: 'string' }],
236+
raw: 'Array<string>',
237+
},
238+
},
229239
],
230240
return: { name: 'boolean' },
231241
},
232-
raw: '(p1: number, p2: ?string) => boolean',
242+
raw: '(p1: number, p2: ?string, ...rest: Array<string>) => boolean',
233243
});
234244
});
235245

@@ -265,6 +275,7 @@ describe('getFlowType', () => {
265275
raw: 'string => boolean',
266276
});
267277
});
278+
268279
it('detects callable signature type', () => {
269280
const typePath = expression('x: { (str: string): string, token: string }')
270281
.get('typeAnnotation')

src/utils/__tests__/getTSType-test.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ describe('getTSType', () => {
185185
});
186186

187187
it('detects function signature type', () => {
188-
const typePath = expression('x: (p1: number, p2: string) => boolean')
188+
const typePath = expression(
189+
'x: (p1: number, p2: string, ...rest: Array<string>) => boolean',
190+
)
189191
.get('typeAnnotation')
190192
.get('typeAnnotation');
191193
expect(getTSType(typePath)).toEqual({
@@ -195,10 +197,18 @@ describe('getTSType', () => {
195197
arguments: [
196198
{ name: 'p1', type: { name: 'number' } },
197199
{ name: 'p2', type: { name: 'string' } },
200+
{
201+
name: 'rest',
202+
type: {
203+
name: 'Array',
204+
elements: [{ name: 'string' }],
205+
raw: 'Array<string>',
206+
},
207+
},
198208
],
199209
return: { name: 'boolean' },
200210
},
201-
raw: '(p1: number, p2: string) => boolean',
211+
raw: '(p1: number, p2: string, ...rest: Array<string>) => boolean',
202212
});
203213
});
204214

src/utils/getFlowType.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,27 @@ function handleFunctionTypeAnnotation(
266266

267267
path.get('params').each(param => {
268268
const typeAnnotation = getTypeAnnotation(param);
269-
if (!typeAnnotation) return;
270269

271270
type.signature.arguments.push({
272271
name: param.node.name ? param.node.name.name : '',
273-
type: getFlowTypeWithResolvedTypes(typeAnnotation, typeParams),
272+
type: typeAnnotation
273+
? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams)
274+
: null,
274275
});
275276
});
276277

278+
if (path.node.rest) {
279+
const rest = path.get('rest');
280+
const typeAnnotation = getTypeAnnotation(rest);
281+
282+
type.signature.arguments.push({
283+
name: rest.node.name ? rest.node.name.name : '',
284+
type: typeAnnotation
285+
? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams)
286+
: null,
287+
});
288+
}
289+
277290
return type;
278291
}
279292

src/utils/getTSType.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const tsTypes = {
3030
TSAnyKeyword: 'any',
3131
TSBooleanKeyword: 'boolean',
3232
TSUnknownKeyword: 'unknown',
33+
TSNeverKeyword: 'never',
3334
TSNullKeyword: 'null',
3435
TSUndefinedKeyword: 'undefined',
3536
TSNumberKeyword: 'number',
@@ -227,11 +228,17 @@ function handleTSFunctionType(
227228

228229
path.get('parameters').each(param => {
229230
const typeAnnotation = getTypeAnnotation(param);
230-
if (!typeAnnotation) return;
231+
232+
let name = param.node.name || '';
233+
if (param.node.type === 'RestElement') {
234+
name = param.node.argument.name;
235+
}
231236

232237
type.signature.arguments.push({
233-
name: param.node.name || '',
234-
type: getTSTypeWithResolvedTypes(typeAnnotation, typeParams),
238+
name,
239+
type: typeAnnotation
240+
? getTSTypeWithResolvedTypes(typeAnnotation, typeParams)
241+
: null,
235242
});
236243
});
237244

0 commit comments

Comments
 (0)