Skip to content

Commit ed12374

Browse files
bebrawNoviny
authored andcommitted
Support decorators + fix issue related to custom props in functions (#54)
* fix: Fix decorator support and allow default props to be missing * test: Add tests to cover addDefaultProps fix * test: Add a test against decorator support in typescript * fix: Fix lookup for nested type names I.e. Texture["foo"]. Previously it returned `[Object object].foo`. Now it captures the correct name. * fix: Include `key` field to ´TSTypeReference` This way array definitions contain keys. Previously this information wasn't included making it impossible to introspect. * chore: Add a flow fixme to make the build pass
1 parent 914e372 commit ed12374

File tree

3 files changed

+241
-2
lines changed

3 files changed

+241
-2
lines changed

packages/extract-react-types/__snapshots__/test.js.snap

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3549,6 +3549,9 @@ Object {
35493549
"kind": "property",
35503550
"optional": false,
35513551
"value": Object {
3552+
"key": Object {
3553+
"kind": "any",
3554+
},
35523555
"kind": "generic",
35533556
"typeParams": Object {
35543557
"kind": "typeParams",
@@ -3575,6 +3578,84 @@ Object {
35753578
}
35763579
`;
35773580

3581+
exports[`ts array prop 1`] = `
3582+
Object {
3583+
"component": Object {
3584+
"kind": "generic",
3585+
"name": Object {
3586+
"kind": "id",
3587+
"name": "Schedule",
3588+
"type": null,
3589+
},
3590+
"value": Object {
3591+
"kind": "object",
3592+
"members": Array [
3593+
Object {
3594+
"key": Object {
3595+
"kind": "id",
3596+
"name": "intervals",
3597+
},
3598+
"kind": "property",
3599+
"optional": false,
3600+
"value": Object {
3601+
"key": Object {
3602+
"kind": "any",
3603+
},
3604+
"kind": "generic",
3605+
"typeParams": Object {
3606+
"kind": "typeParams",
3607+
"params": Array [
3608+
Object {
3609+
"kind": "object",
3610+
"members": Array [
3611+
Object {
3612+
"key": Object {
3613+
"kind": "id",
3614+
"name": "begin",
3615+
},
3616+
"kind": "property",
3617+
"optional": false,
3618+
"value": Object {
3619+
"kind": "generic",
3620+
"value": Object {
3621+
"kind": "id",
3622+
"name": "Interval['begin']",
3623+
},
3624+
},
3625+
},
3626+
Object {
3627+
"key": Object {
3628+
"kind": "id",
3629+
"name": "end",
3630+
},
3631+
"kind": "property",
3632+
"optional": false,
3633+
"value": Object {
3634+
"kind": "generic",
3635+
"value": Object {
3636+
"kind": "id",
3637+
"name": "Interval['end']",
3638+
},
3639+
},
3640+
},
3641+
],
3642+
},
3643+
],
3644+
},
3645+
"value": Object {
3646+
"kind": "id",
3647+
"name": "Array",
3648+
},
3649+
},
3650+
},
3651+
],
3652+
"referenceIdName": "ScheduleProps",
3653+
},
3654+
},
3655+
"kind": "program",
3656+
}
3657+
`;
3658+
35783659
exports[`ts boolean 1`] = `
35793660
Object {
35803661
"component": Object {
@@ -3645,6 +3726,52 @@ Object {
36453726
}
36463727
`;
36473728

3729+
exports[`ts custom prop 1`] = `
3730+
Object {
3731+
"component": Object {
3732+
"kind": "generic",
3733+
"name": Object {
3734+
"kind": "id",
3735+
"name": "Badge",
3736+
"type": null,
3737+
},
3738+
"value": Object {
3739+
"kind": "object",
3740+
"members": Array [
3741+
Object {
3742+
"key": Object {
3743+
"kind": "id",
3744+
"name": "texture",
3745+
},
3746+
"kind": "property",
3747+
"optional": false,
3748+
"value": Object {
3749+
"kind": "string",
3750+
},
3751+
},
3752+
],
3753+
"referenceIdName": "BadgeProps",
3754+
},
3755+
},
3756+
"kind": "program",
3757+
}
3758+
`;
3759+
3760+
exports[`ts decorators 1`] = `
3761+
Object {
3762+
"component": Object {
3763+
"kind": "object",
3764+
"members": Array [],
3765+
"name": Object {
3766+
"kind": "id",
3767+
"name": "Theme",
3768+
"type": null,
3769+
},
3770+
},
3771+
"kind": "program",
3772+
}
3773+
`;
3774+
36483775
exports[`ts different React components 1`] = `
36493776
Object {
36503777
"component": Object {
@@ -3989,6 +4116,41 @@ Object {
39894116
}
39904117
`;
39914118

4119+
exports[`ts nested prop 1`] = `
4120+
Object {
4121+
"component": Object {
4122+
"kind": "generic",
4123+
"name": Object {
4124+
"kind": "id",
4125+
"name": "Badge",
4126+
"type": null,
4127+
},
4128+
"value": Object {
4129+
"kind": "object",
4130+
"members": Array [
4131+
Object {
4132+
"key": Object {
4133+
"kind": "id",
4134+
"name": "texture",
4135+
},
4136+
"kind": "property",
4137+
"optional": false,
4138+
"value": Object {
4139+
"kind": "generic",
4140+
"value": Object {
4141+
"kind": "id",
4142+
"name": "Texture['src']",
4143+
},
4144+
},
4145+
},
4146+
],
4147+
"referenceIdName": "BadgeProps",
4148+
},
4149+
},
4150+
"kind": "program",
4151+
}
4152+
`;
4153+
39924154
exports[`ts no react component 1`] = `
39934155
Object {
39944156
"component": undefined,
@@ -4356,6 +4518,9 @@ Object {
43564518
"referenceIdName": "ReactElement",
43574519
"types": Array [
43584520
Object {
4521+
"key": Object {
4522+
"kind": "any",
4523+
},
43594524
"kind": "generic",
43604525
"typeParams": Object {
43614526
"kind": "typeParams",
@@ -4373,6 +4538,9 @@ Object {
43734538
Object {
43744539
"kind": "arrayType",
43754540
"type": Object {
4541+
"key": Object {
4542+
"kind": "any",
4543+
},
43764544
"kind": "generic",
43774545
"typeParams": Object {
43784546
"kind": "typeParams",

packages/extract-react-types/src/index.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ function convertReactComponentFunction(path, context) {
189189
}
190190

191191
function addDefaultProps(props, defaultProps) {
192+
if (!defaultProps) {
193+
return props;
194+
}
195+
192196
defaultProps.forEach(property => {
193197
let ungeneric = resolveFromGeneric(props);
194198
const prop = getProp(ungeneric, property);
@@ -878,11 +882,14 @@ converters.TSIndexedAccessType = (path, context) => {
878882
return member.value;
879883
}
880884
}
885+
886+
const name = type.value.name || type.value.referenceIdName;
887+
881888
return {
882889
kind: 'generic',
883890
value: {
884891
kind: type.value.kind,
885-
name: `${type.value.name || type.value.referenceIdName}['${indexKey}']`
892+
name: `${name.name || name}['${indexKey}']`
886893
}
887894
};
888895
} else {
@@ -949,6 +956,7 @@ converters.TSTypeReference = (path, context) /*: K.Generic */ => {
949956
return {
950957
kind: 'generic',
951958
typeParams: convert(typeParameters, context),
959+
key: convert(path.get('key'), context),
952960
value: convert(path.get('typeName'), context)
953961
};
954962
}
@@ -1426,7 +1434,7 @@ function getContext(
14261434
filename /*:? string */,
14271435
resolveOptions /*:? Object */
14281436
) {
1429-
let plugins = ['jsx'];
1437+
let plugins = ['jsx', ['decorators', { decoratorsBeforeExport: true }]];
14301438
/* eslint-disable-next-line no-param-reassign */
14311439
if (!resolveOptions) resolveOptions = {};
14321440

@@ -1447,6 +1455,7 @@ function getContext(
14471455
throw new Error('typeSystem must be either "flow" or "typescript"');
14481456
}
14491457

1458+
/* $FlowFixMe - need to update types in babylon-options */
14501459
let parserOpts = createBabylonOptions({
14511460
stage: 2,
14521461
plugins

packages/extract-react-types/test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,68 @@ const TESTS = [
374374
}
375375
`
376376
},
377+
{
378+
name: 'ts custom prop',
379+
typeSystem: 'typescript',
380+
code: `
381+
interface BadgeProps {
382+
texture: string;
383+
}
384+
385+
function Badge({ texture }: BadgeProps) {}
386+
387+
Badge.f = [];
388+
389+
export default Badge;
390+
`
391+
},
392+
{
393+
name: 'ts nested prop',
394+
typeSystem: 'typescript',
395+
code: `
396+
interface BadgeProps {
397+
texture: Texture["src"];
398+
}
399+
400+
function Badge({ texture }: BadgeProps) {}
401+
402+
export default Badge;
403+
`
404+
},
405+
{
406+
name: 'ts array prop',
407+
typeSystem: 'typescript',
408+
code: `
409+
interface ScheduleProps {
410+
intervals: Array<{
411+
begin: Interval["begin"];
412+
end: Interval["end"];
413+
}>;
414+
}
415+
416+
function Schedule({ intervals }: ScheduleProps) {}
417+
418+
export default Schedule;
419+
`
420+
},
421+
{
422+
name: 'ts decorators',
423+
typeSystem: 'typescript',
424+
code: `
425+
@ObjectType()
426+
export class Theme extends React.Component<{}, {}> {
427+
@Field(_ => ID)
428+
public id!: string;
429+
430+
@Field(_ => Textures)
431+
public fonts!: Textures;
432+
433+
render() {}
434+
}
435+
436+
export default Theme;
437+
`
438+
},
377439
{
378440
name: 'ts boolean',
379441
typeSystem: 'typescript',

0 commit comments

Comments
 (0)