Skip to content

Commit 08885f1

Browse files
authored
Use question mark token for optional props (lyft#8)
1 parent d7ee147 commit 08885f1

File tree

3 files changed

+28
-24
lines changed

3 files changed

+28
-24
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class MyComponent extends React.Component {
3838
```tsx
3939
type MyComponentProps = {
4040
prop1: string;
41-
prop2: number | undefined;
41+
prop2?: number;
4242
}
4343

4444
type MyComponentState = {

Diff for: src/transforms/react-js-make-props-and-state-transform.ts

+18-14
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,23 @@ export function reactJSMakePropsAndStateInterfaceTransformFactoryFactory(typeChe
222222
console.warn('Bad value for propType', name, 'at', propertyAssignment.getStart());
223223
return result;
224224
}
225-
const typeValue = getTypeFromReactPropTypeExpression(propertyAssignment.initializer);
226225

227226
// Ignore children, React types have it
228227
if (propertyAssignment.name.getText() === 'children') {
229228
return result;
230229
}
230+
231+
// Ignore children, React types have it
232+
if (propertyAssignment.name.getText() === 'children') {
233+
return result;
234+
}
235+
236+
const typeValue = getTypeFromReactPropTypeExpression(propertyAssignment.initializer);
237+
const isOptional = isPropTypeOptional(propertyAssignment.initializer);
231238
const propertySignature = ts.createPropertySignature(
232239
[],
233240
name,
234-
undefined,
241+
isOptional ? ts.createToken(ts.SyntaxKind.QuestionToken): undefined,
235242
typeValue,
236243
undefined,
237244
);
@@ -291,19 +298,16 @@ export function reactJSMakePropsAndStateInterfaceTransformFactoryFactory(typeChe
291298
} else {
292299
result = ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword);
293300
}
301+
return result;
302+
}
294303

295-
if (!/\.isRequired/.test(text)) {
296-
return makeTypeNodeOptional(result);
297-
} else {
298-
return result;
299-
}
300-
301-
function makeTypeNodeOptional(node: ts.TypeNode) {
302-
return ts.createUnionOrIntersectionTypeNode(ts.SyntaxKind.UnionType, [
303-
node,
304-
ts.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
305-
]);
306-
}
304+
/**
305+
* Decide if node is optional
306+
* @param node React propTypes member node
307+
*/
308+
function isPropTypeOptional(node: ts.PropertyAccessExpression) {
309+
const text = node.getText().replace(/React\.PropTypes\./, '');
310+
return !/\.isRequired/.test(text)
307311
}
308312
};
309313
};

Diff for: test/react-js-make-props-and-state-transform/static-proptypes-many-props/output.tsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import * as React from 'react';
22

33
export default class MyComponent extends React.Component<{
4-
any: any | undefined;
5-
array: any[] | undefined;
6-
bool: boolean | undefined;
7-
func: ((...args: any[]) => any) | undefined;
8-
number: number | undefined;
9-
object: object | undefined;
10-
string: string | undefined;
11-
node: (number | string | JSX.Element) | undefined;
12-
element: JSX.Element | undefined;
4+
any?: any;
5+
array?: any[];
6+
bool?: boolean;
7+
func?: (...args: any[]) => any;
8+
number?: number;
9+
object?: object;
10+
string?: string;
11+
node?: number | string | JSX.Element;
12+
element?: JSX.Element;
1313
anyRequired: any;
1414
arrayRequired: any[];
1515
boolRequired: boolean;

0 commit comments

Comments
 (0)