-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix issues with IntersectionTypeAnnotation for prop-types and no-unused-prop-types #1415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix issues with IntersectionTypeAnnotation for prop-types and no-unused-prop-types #1415
Conversation
…opTypes when one of the intersected props is not found, e.g. when imported
lib/rules/no-unused-prop-types.js
Outdated
} | ||
} | ||
|
||
return ignorePropsValidation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i can't decide if this style, or early-returning each place this var is assigned, is better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly I'm in general not really happy about the fact that a function with a name declarePropTypes***
returns a boolean at all. It's a bit confusing. That's why I liked this style a bit more, because it's very explicit to say what those methods return and what the boolean actually means.
Perhaps a try/catch
may be even better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could rename the function instead :-)
lib/rules/no-unused-prop-types.js
Outdated
* @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported) | ||
*/ | ||
function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) { | ||
return propTypes.types.reduce((ignorePropsValidation, annotation) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since this is reducing to a boolean, could it use some
or every
, and that way it will bail early?
lib/rules/no-unused-prop-types.js
Outdated
} | ||
|
||
let types = buildTypeAnnotationDeclarationTypes(value, key); | ||
if (types === true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of reusing types
here, can we use multiple vars and use const
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is from the existing code so didn't touch it yet. But I think we can simply do:
const types = buildTypeAnnotationDeclarationTypes(value, key) || {};
declaredPropTypes.push({
...types,
fullName: key,
name: key,
node: value
});
Edit: Ah! We don't support spread operator yet. 😞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meh, another problem is that buildTypeAnnotationDeclarationTypes
returns either a boolean or an object which isn't great either. I try to refactor it to always return an object, but it needs changes in more places than just here.
But I do think it's a good refactor to do 😄
Made some additional changes. Did a smoke test on the material-ui code which is currently breaking with rc0. I changed those functions to return early, but haven't changed the name as I couldn't come up with something. @yannickcr please also have a look as this is required for 7.4.0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks much better!
@@ -261,7 +262,7 @@ module.exports = { | |||
// If it's a computed property, we can't make any further analysis, but is valid | |||
return key === '__COMPUTED_PROP__'; | |||
} | |||
if (propType === true) { | |||
if (typeof propType === 'object' && Object.keys(propType).length === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the typeof guarding against here? This allows null
, for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
would be checked in the if statement before:
if (!propType) {
// If it's a computed property, we can't make any further analysis, but is valid
return key === '__COMPUTED_PROP__';
}
Otherwise, if I remove the typeof
condition, one test starts failing. Turns out propType
is a function()
in one of the cases (not sure why) and it satifies the condition Object.keys(propType).length === 0
. Perhaps should use https://www.npmjs.com/package/lodash.isplainobject ?
function Hello(props) {
return <div>{props.name.constructor.firstname}</div>
}
Hello.propTypes = {
name: PropTypes.shape({
firstname: PropTypes.object
})
};:
AssertionError: Should have 1 error but had 0: []
Basically we want to check if its {}
instead of true
, since those methods always return an object now instead of a boolean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha; makes sense.
* @param {Object} declaredPropTypes | ||
* @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported) | ||
*/ | ||
function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can these two functions live somewhere they can be shared across the rules that currently duplicate them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I'm working on it 😄 The idea will be that the rule will be declared as:
create: propTypes.detect((context, components, utils) => {
...
})
And this will take care of ALL the shared code between prop-types
and no-unused-prop-types
. Perhaps also for the other rules.
Closes #1413
3 cases needed to be covered:
type Props = PropsA & { foo: string }