New rule: require explicitly typed `defaultProps`
andrewbranch opened this issue · comments
It's easy write a component with unsafe defaultProps:
interface MyComponentProps {
onClick?: React.MouseEventHandler<HTMLElement>;
}
class MyComponent extends React.Component<MyComponentProps> {
static defaultProps = {
onClick: 42
};
render() {
return <div onClick={this.props.onClick} />;
}
}
So it's useful to enforce declaring an explicit type for static defaultProps
(which should basically always be Partial<P>
where P
is the type of the component’s props), which would catch such silly mistakes:
interface MyComponentProps {
onClick?: React.MouseEventHandler<HTMLElement>;
}
class MyComponent extends React.Component<MyComponentProps> {
static defaultProps: Partial<MyComponentProps> = {
// ^^^^^^^^^^^^ Type { onClick: number } is not convertible to Partial<MyComponentProps> or some error message along these lines
onClick: 42
};
}
I think it would be useful and would be happy to accept a PR!
I think to do this right, we’d need to use the type checker (ts.createProgram
) to tell whether or not a class declaring defaultProps
is in fact a React component. However, I'm not sure what the overhead for that is, and if it would be worth it just to check the AST for the text React.Component
and maybe Component
, also checking that Component
is being imported from 'react'
at some point (presumably faster but not as accurate). What are your feelings on it?
Actually, in TypeScript 3.0, you don’t want to explicitly type defaultProps. So, maybe instead of requiring an explicit type, a rule that checks that the inferred type of defaultProps
is assignable to the class’s props interface would be valuable—which would definitely require the type checker.
Also see this discussion (which unfortunately currently seems to be on hold): DefinitelyTyped/DefinitelyTyped#28515
a rule that checks that the inferred type of defaultProps is assignable to the class’s props interface
this sounds like a good idea, but it should now be an eslint rule. see #210