Skip to content

Commit 5fcc7fc

Browse files
committed
Support rest parameters in function signatures
1 parent f2193db commit 5fcc7fc

File tree

5 files changed

+64
-12
lines changed

5 files changed

+64
-12
lines changed

src/types.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,18 @@ export type FlowElementsType = FlowBaseType & {
5959
elements: Array<FlowTypeDescriptor>,
6060
};
6161

62+
export type FlowFunctionArgumentType = {
63+
name: string,
64+
type: FlowTypeDescriptor,
65+
rest?: boolean,
66+
};
67+
6268
export type FlowFunctionSignatureType = FlowBaseType & {
6369
name: 'signature',
6470
type: 'function',
6571
raw: string,
6672
signature: {
67-
arguments: Array<{ name: string, type: FlowTypeDescriptor }>,
73+
arguments: Array<FlowFunctionArgumentType>,
6874
return: FlowTypeDescriptor,
6975
},
7076
};

src/utils/__tests__/getFlowType-test.js

Lines changed: 14 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,19 @@ describe('getFlowType', () => {
226228
arguments: [
227229
{ name: 'p1', type: { name: 'number' } },
228230
{ name: 'p2', type: { name: 'string', nullable: true } },
231+
{
232+
name: 'rest',
233+
rest: true,
234+
type: {
235+
name: 'Array',
236+
elements: [{ name: 'string' }],
237+
raw: 'Array<string>',
238+
},
239+
},
229240
],
230241
return: { name: 'boolean' },
231242
},
232-
raw: '(p1: number, p2: ?string) => boolean',
243+
raw: '(p1: number, p2: ?string, ...rest: Array<string>) => boolean',
233244
});
234245
});
235246

@@ -265,6 +276,7 @@ describe('getFlowType', () => {
265276
raw: 'string => boolean',
266277
});
267278
});
279+
268280
it('detects callable signature type', () => {
269281
const typePath = expression('x: { (str: string): string, token: string }')
270282
.get('typeAnnotation')

src/utils/__tests__/getTSType-test.js

Lines changed: 13 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,19 @@ describe('getTSType', () => {
195197
arguments: [
196198
{ name: 'p1', type: { name: 'number' } },
197199
{ name: 'p2', type: { name: 'string' } },
200+
{
201+
name: 'rest',
202+
rest: true,
203+
type: {
204+
name: 'Array',
205+
elements: [{ name: 'string' }],
206+
raw: 'Array<string>',
207+
},
208+
},
198209
],
199210
return: { name: 'boolean' },
200211
},
201-
raw: '(p1: number, p2: string) => boolean',
212+
raw: '(p1: number, p2: string, ...rest: Array<string>) => boolean',
202213
});
203214
});
204215

src/utils/getFlowType.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,28 @@ 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+
rest: true,
288+
});
289+
}
290+
277291
return type;
278292
}
279293

src/utils/getTSType.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type {
1919
FlowTypeDescriptor,
2020
FlowElementsType,
2121
FlowFunctionSignatureType,
22+
FlowFunctionArgumentType,
2223
FlowObjectSignatureType,
2324
} from '../types';
2425

@@ -30,6 +31,7 @@ const tsTypes = {
3031
TSAnyKeyword: 'any',
3132
TSBooleanKeyword: 'boolean',
3233
TSUnknownKeyword: 'unknown',
34+
TSNeverKeyword: 'never',
3335
TSNullKeyword: 'null',
3436
TSUndefinedKeyword: 'undefined',
3537
TSNumberKeyword: 'number',
@@ -227,12 +229,19 @@ function handleTSFunctionType(
227229

228230
path.get('parameters').each(param => {
229231
const typeAnnotation = getTypeAnnotation(param);
230-
if (!typeAnnotation) return;
231-
232-
type.signature.arguments.push({
232+
const arg: FlowFunctionArgumentType = {
233233
name: param.node.name || '',
234-
type: getTSTypeWithResolvedTypes(typeAnnotation, typeParams),
235-
});
234+
type: typeAnnotation
235+
? getTSTypeWithResolvedTypes(typeAnnotation, typeParams)
236+
: null,
237+
};
238+
239+
if (param.node.type === 'RestElement') {
240+
arg.name = param.node.argument.name;
241+
arg.rest = true;
242+
}
243+
244+
type.signature.arguments.push(arg);
236245
});
237246

238247
return type;

0 commit comments

Comments
 (0)