Skip to content
This repository was archived by the owner on Sep 21, 2019. It is now read-only.

Commit 23fd00e

Browse files
author
Mohsen Azimi
committed
Use question mark token for optional props
1 parent db9e687 commit 23fd00e

File tree

3 files changed

+33
-23
lines changed

3 files changed

+33
-23
lines changed

README.md

Lines changed: 1 addition & 1 deletion
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 = {

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

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,21 @@ export function reactJSMakePropsAndStateInterfaceTransformFactoryFactory(typeChe
222222
console.warn('Bad value for propType', name, 'at', propertyAssignment.getStart());
223223
return result;
224224
}
225+
226+
// Ignore children, React types have it
227+
if (propertyAssignment.name.getText() === 'children') {
228+
return result;
229+
}
230+
225231
const typeValue = getTypeFromReactPropTypeExpression(propertyAssignment.initializer);
226-
const propertySignature = ts.createPropertySignature([], name, undefined, typeValue, undefined);
232+
const isOptional = isPropTypeOptional(propertyAssignment.initializer);
233+
const propertySignature = ts.createPropertySignature(
234+
[],
235+
name,
236+
isOptional ? ts.createToken(ts.SyntaxKind.QuestionToken): undefined,
237+
typeValue,
238+
undefined,
239+
);
227240
result.members.push(propertySignature)
228241
return result;
229242
}, ts.createTypeLiteralNode([]));
@@ -280,19 +293,16 @@ export function reactJSMakePropsAndStateInterfaceTransformFactoryFactory(typeChe
280293
} else {
281294
result = ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword);
282295
}
296+
return result;
297+
}
283298

284-
if (!/\.isRequired/.test(text)) {
285-
return makeTypeNodeOptional(result);
286-
} else {
287-
return result;
288-
}
289-
290-
function makeTypeNodeOptional(node: ts.TypeNode) {
291-
return ts.createUnionOrIntersectionTypeNode(ts.SyntaxKind.UnionType, [
292-
node,
293-
ts.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
294-
]);
295-
}
299+
/**
300+
* Decide if node is optional
301+
* @param node React propTypes member node
302+
*/
303+
function isPropTypeOptional(node: ts.PropertyAccessExpression) {
304+
const text = node.getText().replace(/React\.PropTypes\./, '');
305+
return !/\.isRequired/.test(text)
296306
}
297307
};
298308
};

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

Lines changed: 9 additions & 9 deletions
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)