milesj / babel-plugin-typescript-to-proptypes

Generate React PropTypes from TypeScript interfaces or type aliases.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Difference between TypeScript optional fields and propTypes isRequired

mz8i opened this issue · comments

Consider the following component:

const Foo: React.FC<{bar: boolean}> = (props) => (
    props.bar != undefined ? <h1>Full!</h1> : <h2>Empty.</h2>
);

and its usage in another component's render function:

render() {
    const barProp = null;
    return <Foo bar={barProp} />;
}

Now the problem is with the handling of null/undefined values by TypeScript and propTypes. There is a discrepancy - in TS, the above won't throw an error, because the value for bar is supplied (even though it's null). But babel-plugin-typescript-to-proptypes will generate propTypes with isRequired here (as bar is not marked as optional), and React shows a warning that bar is required but it's null.

I don't feel marking the field in the interface as bar?: boolean is a good approach to solve such an issue, because then <Foo /> would be a valid use of the component, but that can lead to hard-to-spot bugs where a (potentially null-valued) property wasn't passed down the component tree.

On the other hand, having warnings pop up everywhere because of this issue is not great either. Out of a lack of a better idea, I'd suggest having a configuration switch to indicate whether isRequired should be generated at all - this would work if someone wants to just check the types of props at runtime, but not enforce their presence.

Yeah, it's one of those weird scenarios where null is valid value and there's not enough type information. I'm not sure of a solution either besides another option to control this.

Having an option like generateIsRequired would be great - in our project before moving to TypeScript, we only used isRequired in very rare cases anyway, and for quite a few props null is a valid value, so skipping that aspect of generation altogether would make most sense, but currently it's not configurable.

Added a strict option. Will be in next release.