Skip to content

Commit

Permalink
fix: Correctly handle ObjectTypeSpreadProperty in object type annotat…
Browse files Browse the repository at this point in the history
…ions (#593)

Co-authored-by: Daniel Tschinder <231804+danez@users.noreply.github.com>
  • Loading branch information
imdreamrunner and danez committed May 28, 2022
1 parent 4fc5b21 commit 395f338
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
122 changes: 122 additions & 0 deletions src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`getFlowType handles ObjectTypeSpreadProperty 1`] = `
Object {
"name": "signature",
"raw": "{| apple: string, banana: string, ...OtherFruits |}",
"signature": Object {
"properties": Array [
Object {
"key": "apple",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "banana",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "orange",
"value": Object {
"name": "string",
"required": true,
},
},
],
},
"type": "object",
}
`;

exports[`getFlowType handles ObjectTypeSpreadProperty from imported types 1`] = `
Object {
"name": "signature",
"raw": "{| apple: string, banana: string, ...MyType |}",
"signature": Object {
"properties": Array [
Object {
"key": "apple",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "banana",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "a",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "b",
"value": Object {
"name": "notImported",
"nullable": true,
"required": true,
},
},
],
},
"type": "object",
}
`;

exports[`getFlowType handles nested ObjectTypeSpreadProperty 1`] = `
Object {
"name": "signature",
"raw": "{| apple: string, banana: string, ...BreakfastFruits |}",
"signature": Object {
"properties": Array [
Object {
"key": "apple",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "banana",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "mango",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "orange",
"value": Object {
"name": "string",
"required": true,
},
},
Object {
"key": "lemon",
"value": Object {
"name": "string",
"required": true,
},
},
],
},
"type": "object",
}
`;
40 changes: 40 additions & 0 deletions src/utils/__tests__/getFlowType-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1269,4 +1269,44 @@ 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)).toMatchSnapshot();
});

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)).toMatchSnapshot();
});

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

expect(getFlowType(typePath, null, mockImporter)).toMatchSnapshot();
});
});
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

0 comments on commit 395f338

Please sign in to comment.