The "react/default-props-match-prop-types" setting forces looser typing
See original GitHub issueIf you use the optional Flow Linter, you can get warnings for ‘sketchy’ checks, meaning when you do something like if (foo)
or foo ? ... : ...
when foo
is not clearly typed. Example:
type Props = {
isHappy?: boolean,
};
const Emoji = ({ isHappy }: Props) =>
<span>{isHappy ? '😀' : '😭'}</span>;
// ^^^^^^^ Sketchy null check on boolean which is potentially false. Perhaps you meant to check for null or undefined?
Emoji.defaultProps = {
isHappy: false,
};
The linter thinks isHappy
might be undefined, because we have annotated it as a maybe-boolean, but in fact it’s guaranteed to be boolean.
So in fact the Props
definition above is wrong; it should just beisHappy: boolean
, because the props
argument passed into the function is guaranteed always to have a boolean isHappy
value when you render via JSX, thanks to the defaultProps
. The linter is not at fault here, we’re just confusing it by actively loosening the type for a prop that needn’t be loosened.
You can fix the linter warning by changing the Props
to have isHappy: boolean
. (And you can still then render <Emoji />
without type errors, thanks to the defaultProps
.) But doing this breaks compatibility with this eslint-config-airbnb rule:
'react/default-props-match-prop-types': ['error', { allowRequiredDefaults: false }],
This ESLint rule seems, at first glance, to encourage stricter code. But it actually forces you to loosen Flow’s knowledge your props’ types. This causes Flow Linter warnings and may lead to real refinement problems down the line.
So I propose changing it to ['error', { allowRequiredDefaults: true }]
to allow stricter props typing. The meaning of defaultProps
is well established, and it needn’t be visually reinforced with corresponding maybe-types, especially if those maybe-types actually weaken Flow’s understanding of what’s going on.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:2
- Comments:14
Top GitHub Comments
That’s interesting. So it sounds like propTypes more closely match ElementConfig - where ElementProps are your internal props.
So, in that case, I’d say that the react plugin should be requiring ElementConfig, and not just “typed props” - and then all the same rules should apply. ElementProps is something that should be entirely optional.
OK, you were calling it a bug until now. You may see it as a design flaw. But the fact is it works that way, and it’s intentional. Any tooling that claims to support Flow (like eslint-plugin-react) should support it based on how it actually works, or not at all.
FWIW, the React project seems to fully support Flow’s design here, and they export utility types that embrace the distinction:
React.ElementConfig
works out a component’s ‘config’ type (to match attributes in a JSX/React.createElement
expression), whileReact.ElementProps
gets you the type of the ‘props’ object passed into the function. These two types are treated and discussed as different things, in both the Flow docs and the React docs. It’s how things are and it’s not going to change. Personally I think it’s a useful distinction to make.