Skip to content

Commit 1812a3d

Browse files
imdreamrunnerdanez
andcommitted
fix: Correctly handle ObjectTypeSpreadProperty in object type annotations (#593)
Co-authored-by: Daniel Tschinder <[email protected]>
1 parent 70b667f commit 1812a3d

File tree

3 files changed

+158
-0
lines changed

3 files changed

+158
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`getFlowType handles ObjectTypeSpreadProperty 1`] = `
4+
Object {
5+
"name": "signature",
6+
"raw": "{| apple: string, banana: string, ...OtherFruits |}",
7+
"signature": Object {
8+
"properties": Array [
9+
Object {
10+
"key": "apple",
11+
"value": Object {
12+
"name": "string",
13+
"required": true,
14+
},
15+
},
16+
Object {
17+
"key": "banana",
18+
"value": Object {
19+
"name": "string",
20+
"required": true,
21+
},
22+
},
23+
Object {
24+
"key": "orange",
25+
"value": Object {
26+
"name": "string",
27+
"required": true,
28+
},
29+
},
30+
],
31+
},
32+
"type": "object",
33+
}
34+
`;
35+
36+
exports[`getFlowType handles nested ObjectTypeSpreadProperty 1`] = `
37+
Object {
38+
"name": "signature",
39+
"raw": "{| apple: string, banana: string, ...BreakfastFruits |}",
40+
"signature": Object {
41+
"properties": Array [
42+
Object {
43+
"key": "apple",
44+
"value": Object {
45+
"name": "string",
46+
"required": true,
47+
},
48+
},
49+
Object {
50+
"key": "banana",
51+
"value": Object {
52+
"name": "string",
53+
"required": true,
54+
},
55+
},
56+
Object {
57+
"key": "mango",
58+
"value": Object {
59+
"name": "string",
60+
"required": true,
61+
},
62+
},
63+
Object {
64+
"key": "orange",
65+
"value": Object {
66+
"name": "string",
67+
"required": true,
68+
},
69+
},
70+
Object {
71+
"key": "lemon",
72+
"value": Object {
73+
"name": "string",
74+
"required": true,
75+
},
76+
},
77+
],
78+
},
79+
"type": "object",
80+
}
81+
`;
82+
83+
exports[`getFlowType handles unresolved ObjectTypeSpreadProperty 1`] = `
84+
Object {
85+
"name": "signature",
86+
"raw": "{| apple: string, banana: string, ...MyType |}",
87+
"signature": Object {
88+
"properties": Array [
89+
Object {
90+
"key": "apple",
91+
"value": Object {
92+
"name": "string",
93+
"required": true,
94+
},
95+
},
96+
Object {
97+
"key": "banana",
98+
"value": Object {
99+
"name": "string",
100+
"required": true,
101+
},
102+
},
103+
],
104+
},
105+
"type": "object",
106+
}
107+
`;

src/utils/__tests__/getFlowType-test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,4 +745,43 @@ describe('getFlowType', () => {
745745
raw: '{ subAction: SubAction }',
746746
});
747747
});
748+
749+
it('handles ObjectTypeSpreadProperty', () => {
750+
const typePath = statement(`
751+
var x: {| apple: string, banana: string, ...OtherFruits |} = 2;
752+
type OtherFruits = { orange: string }
753+
`)
754+
.get('declarations', 0)
755+
.get('id')
756+
.get('typeAnnotation')
757+
.get('typeAnnotation');
758+
759+
expect(getFlowType(typePath)).toMatchSnapshot();
760+
});
761+
762+
it('handles unresolved ObjectTypeSpreadProperty', () => {
763+
const typePath = statement(`
764+
var x: {| apple: string, banana: string, ...MyType |} = 2;
765+
`)
766+
.get('declarations', 0)
767+
.get('id')
768+
.get('typeAnnotation')
769+
.get('typeAnnotation');
770+
771+
expect(getFlowType(typePath)).toMatchSnapshot();
772+
});
773+
774+
it('handles nested ObjectTypeSpreadProperty', () => {
775+
const typePath = statement(`
776+
var x: {| apple: string, banana: string, ...BreakfastFruits |} = 2;
777+
type BreakfastFruits = { mango: string, ...CitrusFruits };
778+
type CitrusFruits = { orange: string, lemon: string };
779+
`)
780+
.get('declarations', 0)
781+
.get('id')
782+
.get('typeAnnotation')
783+
.get('typeAnnotation');
784+
785+
expect(getFlowType(typePath)).toMatchSnapshot();
786+
});
748787
});

src/utils/getFlowType.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ function handleObjectTypeAnnotation(
201201
key: ((getPropertyName(param): any): string),
202202
value: getFlowTypeWithRequirements(param.get('value'), typeParams),
203203
});
204+
} else if (t.ObjectTypeSpreadProperty.check(param.node)) {
205+
let spreadObject = resolveToValue(param.get('argument'));
206+
if (t.GenericTypeAnnotation.check(spreadObject.node)) {
207+
const typeAlias = resolveToValue(spreadObject.get('id'));
208+
if (t.ObjectTypeAnnotation.check(typeAlias.get('right').node)) {
209+
spreadObject = resolveToValue(typeAlias.get('right'));
210+
}
211+
}
212+
if (t.ObjectTypeAnnotation.check(spreadObject.node)) {
213+
const props = handleObjectTypeAnnotation(spreadObject, typeParams);
214+
type.signature.properties.push(...props.signature.properties);
215+
}
204216
}
205217
});
206218

0 commit comments

Comments
 (0)