Skip to content

Commit 117f939

Browse files
committed
Support enums.
1 parent c976242 commit 117f939

File tree

6 files changed

+163
-1
lines changed

6 files changed

+163
-1
lines changed

src/convertBabelToPropTypes.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { types as t } from '@babel/core';
99
import { addComment } from '@babel/types';
1010
import { convertSymbolFromSource } from './convertTSToPropTypes';
11+
import extractEnumValues from './extractEnumValues';
1112
import getTypeName from './getTypeName';
1213
import {
1314
createCall,
@@ -75,6 +76,24 @@ function convert(type: any, state: ConvertState, depth: number): PropType | null
7576
propTypesImportedName,
7677
);
7778

79+
// enum Foo {} -> PropTypes.oneOf
80+
} else if (t.isTSEnumDeclaration(type)) {
81+
return createCall(
82+
t.identifier('oneOf'),
83+
[
84+
t.arrayExpression(
85+
extractEnumValues(type).map(value => {
86+
if (typeof value === 'number') {
87+
return t.numericLiteral(value);
88+
}
89+
90+
return t.stringLiteral(value);
91+
}),
92+
),
93+
],
94+
propTypesImportedName,
95+
);
96+
7897
// (() => void) -> PropTypes.func
7998
} else if (t.isTSFunctionType(type)) {
8099
return createMember(t.identifier('func'), propTypesImportedName);

src/extractEnumValues.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { types as t } from '@babel/core';
2+
3+
export default function extractEnumValues(enumDecl: t.TSEnumDeclaration): (string | number)[] {
4+
const values: (string | number)[] = [];
5+
let lastIndex = -1;
6+
7+
enumDecl.members.forEach(({ initializer }) => {
8+
if (initializer) {
9+
if (t.isNumericLiteral(initializer)) {
10+
lastIndex = initializer.value;
11+
values.push(initializer.value);
12+
} else if (t.isStringLiteral(initializer)) {
13+
values.push(initializer.value);
14+
} else {
15+
// Skip
16+
}
17+
} else {
18+
lastIndex += 1;
19+
values.push(lastIndex);
20+
}
21+
});
22+
23+
return values;
24+
}

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,11 @@ export default declare((api: any, options: PluginOptions, root: string) => {
232232
}
233233
},
234234

235+
// `enum Foo {}`
236+
TSEnumDeclaration({ node }: Path<t.TSInterfaceDeclaration>) {
237+
state.referenceTypes[node.id.name] = node;
238+
},
239+
235240
// `interface FooProps {}`
236241
TSInterfaceDeclaration({ node }: Path<t.TSInterfaceDeclaration>) {
237242
state.componentTypes[node.id.name] = extractTypeProperties(

src/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ export interface ConvertState {
4040
hasImport: boolean;
4141
};
4242
reactImportedName: string;
43-
referenceTypes: { [key: string]: t.TSInterfaceDeclaration | t.TSTypeAliasDeclaration };
43+
referenceTypes: {
44+
[key: string]: t.TSEnumDeclaration | t.TSInterfaceDeclaration | t.TSTypeAliasDeclaration;
45+
};
4446
typeChecker?: ts.TypeChecker;
4547
typeProgram?: ts.Program;
4648
}

tests/__snapshots__/index.test.ts.snap

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,65 @@ export default class TypeComplex extends React.Component<Props> {
12161216
}"
12171217
`;
12181218
1219+
exports[`babel-plugin-typescript-to-proptypes transforms ./fixtures/type-enum.ts 1`] = `
1220+
"import _pt from 'prop-types';
1221+
import React from 'react';
1222+
enum Standard {
1223+
FOO,
1224+
BAR,
1225+
BAZ,
1226+
}
1227+
enum FirstInitializer {
1228+
FOO = 10,
1229+
BAR,
1230+
BAZ,
1231+
}
1232+
enum AllNumbers {
1233+
FOO = 10,
1234+
BAR = 20,
1235+
BAZ = 30,
1236+
}
1237+
enum AllStrings {
1238+
FOO = 'Foo',
1239+
BAR = 'Bar',
1240+
BAZ = 'Baz',
1241+
}
1242+
enum MixedTypes {
1243+
FOO = 1,
1244+
BAR = 'Bar',
1245+
BAZ = 2,
1246+
}
1247+
const enum ConstEnum {
1248+
Up,
1249+
Down,
1250+
Left,
1251+
Right,
1252+
}
1253+
export interface Props {
1254+
standard: Standard;
1255+
first?: FirstInitializer;
1256+
numbers?: AllNumbers;
1257+
strings: AllStrings;
1258+
mixed?: MixedTypes;
1259+
constant?: ConstEnum;
1260+
}
1261+
export default class TypeEnum extends React.Component<Props> {
1262+
static propTypes = {
1263+
standard: _pt.oneOf([0, 1, 2]).isRequired,
1264+
first: _pt.oneOf([10, 11, 12]),
1265+
numbers: _pt.oneOf([10, 20, 30]),
1266+
strings: _pt.oneOf(['Foo', 'Bar', 'Baz']).isRequired,
1267+
mixed: _pt.oneOf([1, 'Bar', 2]),
1268+
constant: _pt.oneOf([0, 1, 2, 3])
1269+
};
1270+
1271+
render() {
1272+
return null;
1273+
}
1274+
1275+
}"
1276+
`;
1277+
12191278
exports[`babel-plugin-typescript-to-proptypes transforms ./fixtures/type-function.ts 1`] = `
12201279
"import _pt from 'prop-types';
12211280
import React from 'react';

tests/fixtures/type-enum.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from 'react';
2+
3+
enum Standard {
4+
FOO,
5+
BAR,
6+
BAZ,
7+
}
8+
9+
enum FirstInitializer {
10+
FOO = 10,
11+
BAR,
12+
BAZ,
13+
}
14+
15+
enum AllNumbers {
16+
FOO = 10,
17+
BAR = 20,
18+
BAZ = 30,
19+
}
20+
21+
enum AllStrings {
22+
FOO = 'Foo',
23+
BAR = 'Bar',
24+
BAZ = 'Baz',
25+
}
26+
27+
enum MixedTypes {
28+
FOO = 1,
29+
BAR = 'Bar',
30+
BAZ = 2,
31+
}
32+
33+
const enum ConstEnum {
34+
Up,
35+
Down,
36+
Left,
37+
Right,
38+
}
39+
40+
export interface Props {
41+
standard: Standard;
42+
first?: FirstInitializer;
43+
numbers?: AllNumbers;
44+
strings: AllStrings;
45+
mixed?: MixedTypes;
46+
constant?: ConstEnum;
47+
}
48+
49+
export default class TypeEnum extends React.Component<Props> {
50+
render() {
51+
return null;
52+
}
53+
}

0 commit comments

Comments
 (0)