DEV Community

Notes on TypeScript: Inferring React PropTypes

A. Sharif on March 10, 2019

Introduction These notes should help in better understanding TypeScript and might be helpful when needing to lookup up how to leverage T...
Collapse
 
pacahon profile image
Sergei •

Thanks for the article. I've tried this solution, but stuck with an error:

Type 'string | null | undefined' is not assignable to type 'string | undefined'

<div className={className}
                  ~~~~~~~~~

  node_modules/@types/react/index.d.ts:1645:9
    1645         className?: string;

I'm using React class component declaration and @types/react

const defaultProps = {
    className: 'user'
};
const propTypes = {
    className: PropTypes.string,
};

class User extends React.Component<UserProps> {
    static defaultProps = defaultProps;
    static propTypes: {};

    render() {
        let {className} = this.props;
        return (
            <div className={className}>test</div>
        );
    }
}
User.propTypes = propTypes;

Without declaring className on propTypes it fails with an error Property 'className' does not exist on type'Readonly<InferPropTypes<{...`

What could be the reason for this?

Collapse
 
busypeoples profile image
A. Sharif •

Thanks for the question. Could you build a codesandbox example, so we can see the complete example and then try to fix it from there?

Collapse
 
pacahon profile image
Sergei •

Sure, here it is codesandbox.io/s/weathered-snowfla...
Looks like If disable strict mode in tsconfig.json it works fine.

Thread Thread
 
busypeoples profile image
A. Sharif •

Excellent, thanks!
Will try it out and provide some feedback.

Collapse
 
noriste profile image
Stefano Magni •

Thank you for your amazing article!! 👏
One question: how do you manage callback props? The solution above does not help with them because the proptypes does not allow to manage them effectively. For example, I could have this ComponentProps type in my component

export interface ComponentProps {
  handleCheckboxChange: (id: string, checked: boolean) => void;
}

how could I update the InferPropTypes type to be prompted by TS if I pass a callback with a wrong signature?
Thank you so much

Collapse
 
busypeoples profile image
A. Sharif •

Thanks for the kind words!
I will have a closer look tomorrow and try to provide more insights if possible.

Collapse
 
adham_benhawy profile image
Adham El Banhawy •

That's really interesting. I didn't know you can still use propTypes with TypeScript, I just always assumed that you gotta always write interfaces for props.

 
busypeoples profile image
A. Sharif •

If you add the defaultProps definition to the Text component, it should probably be enough for TypeScript to figure out that the property is optional.

Text.defaultProps = {
  size: 5
};
 
busypeoples profile image
A. Sharif •

This is interesting. Can you take a look at the simplified example:
codesandbox.io/s/fancy-bird-vqd9x

If you remove defaultProps TypeScript will complain.

Thread Thread
 
busypeoples profile image
A. Sharif •

I think the problem in this specific case is tied to using forwardRef. Will try to find out in more detail , but I think forwardRef drops any default props.

 
busypeoples profile image
A. Sharif •

Yes, I think the problem is within forwardRef in this case. It drops the defaultProps.

Collapse
 
busypeoples profile image
A. Sharif •

Excellent, thanks! Will have a look at this and try to figure out how we can solve this.

Collapse
 
squidsoup profile image
Kit Randel •

Thanks for the excellent post. How do you manage typing spread props?

Collapse
 
busypeoples profile image
A. Sharif •

Sorry, haven't been checking any comments for some time now. Will look into this and add more information.

Collapse
 
dmorrison profile image
Derek Morrison •

I'm confused. In the first example, the (optional) active prop is of type PropTypes.Requireable<boolean>.

Doesn't that mean it's required? What does "requireable" mean?

Collapse
 
dmorrison profile image
Derek Morrison •

Ohhhhh - nevermind. That Requireable interface has a method on it called isRequired. So, it's for things can possibly can be made required. 👍

 
busypeoples profile image
A. Sharif •

Thanks for the clarification!