Skip to content

Commit

Permalink
Add IntersectionTypeAnnotation support to default-props-match-prop-types
Browse files Browse the repository at this point in the history
  • Loading branch information
Joachim Seminck committed Aug 29, 2017
1 parent c7cf2ae commit 00106e4
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
33 changes: 28 additions & 5 deletions lib/rules/default-props-match-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,23 +163,47 @@ module.exports = {
}));
}

/**
* Handles Props defined in IntersectionTypeAnnotation nodes
* e.g. type Props = PropsA & PropsB
* @param {ASTNode} intersectionTypeAnnotation ObjectExpression node.
* @returns {Object[]}
*/
function getPropertiesFromIntersectionTypeAnnotationNode(annotation) {
return annotation.types.reduce((properties, type) => {
annotation = resolveGenericTypeAnnotation(type);

if (annotation && annotation.id) {
annotation = findVariableByName(annotation.id.name);
}

return properties.concat(annotation.properties);
}, []);
}

/**
* Extracts a PropType from a TypeAnnotation node.
* @param {ASTNode} node TypeAnnotation node.
* @returns {Object[]} Array of PropType object representations, to be consumed by `addPropTypesToComponent`.
*/
function getPropTypesFromTypeAnnotation(node) {
let properties;
let properties = [];

switch (node.typeAnnotation.type) {
case 'GenericTypeAnnotation':
let annotation = resolveGenericTypeAnnotation(node.typeAnnotation);

if (annotation && annotation.id) {
annotation = findVariableByName(annotation.id.name);
if (annotation && annotation.type === 'IntersectionTypeAnnotation') {
properties = getPropertiesFromIntersectionTypeAnnotationNode(annotation);
} else {
if (annotation && annotation.id) {
annotation = findVariableByName(annotation.id.name);
}

properties = annotation ? (annotation.properties || []) : [];
}

properties = annotation ? (annotation.properties || []) : [];

break;

case 'UnionTypeAnnotation':
Expand Down Expand Up @@ -314,7 +338,6 @@ module.exports = {
if (!component) {
return;
}

addPropTypesToComponent(component, getPropTypesFromTypeAnnotation(node.typeAnnotation, context));
}

Expand Down
48 changes: 48 additions & 0 deletions tests/lib/rules/default-props-match-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,26 @@ ruleTester.run('default-props-match-prop-types', rule, {
].join('\n'),
parser: 'babel-eslint'
},
{
code: `
type PropsA = { foo?: string };
type PropsB = { bar?: string, fooBar: string };
type Props = PropsA & PropsB;
class Bar extends React.Component {
props: Props;
static defaultProps = {
foo: "foo",
bar: "bar",
}
render() {
return <div>{this.props.foo} - {this.props.bar}</div>
}
}
`,
parser: 'babel-eslint'
},
{
code: [
'import type Props from "fake";',
Expand Down Expand Up @@ -1509,6 +1529,34 @@ ruleTester.run('default-props-match-prop-types', rule, {
column: 36
}
]
},
{
code: `
type PropsA = { foo: string };
type PropsB = { bar: string };
type Props = PropsA & PropsB;
class Bar extends React.Component {
props: Props;
static defaultProps = {
fooBar: "fooBar",
foo: "foo",
}
render() {
return <div>{this.props.foo} - {this.props.bar}</div>
}
}
`,
parser: 'babel-eslint',
errors: [
{
message: 'defaultProp "fooBar" has no corresponding propTypes declaration.'
},
{
message: 'defaultProp "foo" defined for isRequired propType.'
}
]
}
]
});

0 comments on commit 00106e4

Please sign in to comment.