Skip to content

Commit 87aca04

Browse files
committed
Add support for multiple Flow IntersectionTypeAnnotations and skip propTypes when one of the intersected props is not found, e.g. when imported
1 parent f1e86b5 commit 87aca04

File tree

2 files changed

+87
-10
lines changed

2 files changed

+87
-10
lines changed

lib/rules/prop-types.js

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,41 @@ module.exports = {
710710
});
711711
}
712712

713+
/**
714+
* Marks all props found inside IntersectionTypeAnnotation as declared.
715+
* Since InterSectionTypeAnnotations can be nested, this handles recursively.
716+
*
717+
* Modifies the declaredPropTypes object
718+
* @param {ASTNode} propTypes
719+
* @param {Object} declaredPropTypes
720+
* @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
721+
*/
722+
function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) {
723+
let ignorePropsValidation = false;
724+
725+
propTypes.types.forEach(annotation => {
726+
const typeNode = typeScope(annotation.id.name);
727+
if (!typeNode) {
728+
ignorePropsValidation = true;
729+
return;
730+
}
731+
732+
if (typeNode.type === 'IntersectionTypeAnnotation') {
733+
ignorePropsValidation = declarePropTypesForIntersectionTypeAnnotation(typeNode, declaredPropTypes);
734+
} else {
735+
iterateProperties(typeNode.properties, (key, value) => {
736+
if (!value) {
737+
ignorePropsValidation = true;
738+
return;
739+
}
740+
declaredPropTypes[key] = buildTypeAnnotationDeclarationTypes(value);
741+
});
742+
}
743+
});
744+
745+
return ignorePropsValidation;
746+
}
747+
713748
/**
714749
* Mark a prop type as declared
715750
* @param {ASTNode} node The AST node being checked.
@@ -793,16 +828,7 @@ module.exports = {
793828
}
794829
break;
795830
case 'IntersectionTypeAnnotation':
796-
propTypes.types.forEach(annotation => {
797-
const propsType = typeScope(annotation.id.name);
798-
iterateProperties(propsType.properties, (key, value) => {
799-
if (!value) {
800-
ignorePropsValidation = true;
801-
return;
802-
}
803-
declaredPropTypes[key] = buildTypeAnnotationDeclarationTypes(value);
804-
});
805-
});
831+
ignorePropsValidation = declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes);
806832
break;
807833
case null:
808834
break;

tests/lib/rules/prop-types.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,38 @@ ruleTester.run('prop-types', rule, {
16841684
}
16851685
`,
16861686
parser: 'babel-eslint'
1687+
}, {
1688+
code: `
1689+
type PropsA = { foo: string };
1690+
type PropsB = { bar: string };
1691+
type PropsC = { zap: string };
1692+
type Props = PropsA & PropsB;
1693+
1694+
class Bar extends React.Component {
1695+
props: Props & PropsC;
1696+
1697+
render() {
1698+
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
1699+
}
1700+
}
1701+
`,
1702+
parser: 'babel-eslint'
1703+
}, {
1704+
code: `
1705+
import type { PropsA } from "./myPropsA";
1706+
type PropsB = { bar: string };
1707+
type PropsC = { zap: string };
1708+
type Props = PropsA & PropsB;
1709+
1710+
class Bar extends React.Component {
1711+
props: Props & PropsC;
1712+
1713+
render() {
1714+
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
1715+
}
1716+
}
1717+
`,
1718+
parser: 'babel-eslint'
16871719
}, {
16881720
code: `
16891721
type Props = { foo: string }
@@ -3375,6 +3407,25 @@ ruleTester.run('prop-types', rule, {
33753407
errors: [{
33763408
message: '\'fooBar\' is missing in props validation'
33773409
}]
3410+
}, {
3411+
code: `
3412+
type PropsA = { foo: string };
3413+
type PropsB = { bar: string };
3414+
type PropsC = { zap: string };
3415+
type Props = PropsA & PropsB;
3416+
3417+
class Bar extends React.Component {
3418+
props: Props & PropsC;
3419+
3420+
render() {
3421+
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap} - {this.props.fooBar}</div>
3422+
}
3423+
}
3424+
`,
3425+
parser: 'babel-eslint',
3426+
errors: [{
3427+
message: '\'fooBar\' is missing in props validation'
3428+
}]
33783429
}
33793430
]
33803431
});

0 commit comments

Comments
 (0)