Skip to content
92 changes: 92 additions & 0 deletions src/utils/__tests__/getFlowType-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1269,4 +1269,96 @@ describe('getFlowType', () => {
raw: '{ subAction: SubAction }',
});
});

it('handles ObjectTypeSpreadProperty', () => {
const typePath = statement(`
var x: {| apple: string, banana: string, ...OtherFruits |} = 2;
type OtherFruits = { orange: string }
`)
.get('declarations', 0)
.get('id')
.get('typeAnnotation')
.get('typeAnnotation');

expect(getFlowType(typePath, null, noopImporter)).toEqual({
name: 'signature',
type: 'object',
signature: {
properties: [
{
key: 'apple',
value: {
name: 'string',
required: true,
},
},
{
key: 'banana',
value: {
name: 'string',
required: true,
},
},
{
key: 'orange',
value: {
name: 'string',
required: true,
},
},
],
},
raw: '{| apple: string, banana: string, ...OtherFruits |}',
});
});

it('handles ObjectTypeSpreadProperty from imported types', () => {
const typePath = statement(`
var x: {| apple: string, banana: string, ...MyType |} = 2;
import type { MyType } from 'MyType';
`)
.get('declarations', 0)
.get('id')
.get('typeAnnotation')
.get('typeAnnotation');

expect(getFlowType(typePath, null, mockImporter)).toEqual({
name: 'signature',
type: 'object',
signature: {
properties: [
{
key: 'apple',
value: {
name: 'string',
required: true,
},
},
{
key: 'banana',
value: {
name: 'string',
required: true,
},
},
{
key: 'a',
value: {
name: 'string',
required: true,
},
},
{
key: 'b',
value: {
name: 'notImported',
nullable: true,
required: true,
},
},
],
},
raw: '{| apple: string, banana: string, ...MyType |}',
});
});
});
14 changes: 14 additions & 0 deletions src/utils/getFlowType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,20 @@ function handleObjectTypeAnnotation(
importer,
),
});
} else if (t.ObjectTypeSpreadProperty.check(param.node)) {
let spreadObject = resolveToValue(param.get('argument'), importer);
if (t.GenericTypeAnnotation.check(spreadObject.value)) {
const typeAlias = resolveToValue(spreadObject.get('id'), importer);
if (t.ObjectTypeAnnotation.check(typeAlias.get('right').value)) {
spreadObject = resolveToValue(typeAlias.get('right'), importer);
}
}
const props = handleObjectTypeAnnotation(
spreadObject,
typeParams,
importer,
) as ObjectSignatureType;
type.signature.properties.push(...props.signature.properties);
}
});

Expand Down