Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating PropTypes for React Components written in TypeScript

We're creating a library of components for our internal applications. The old version of that library was written in JavaScript and JSX, thus we have declared propTypes for all the components for type-safety.
The newer version of the component library is written in TypeScript. For type-safety we used interfaces for PropTypes such as the following -

interface Props {
    size?: 'small' | 'large';
    color?: string;
    text?: string;
}
export class MyComponent extends React.Component<Props, any> { ... }

This was working fine since the newer projects using those components were written in TypeScript too (We do publish d.ts file for all the component classes). Now we needed to update the component library in the old projects too. Since they were not using TypeScript, the type-safety were not working. They're still relying on the old propTypes way for type-safety.

//Usage of MyComponent
<MyComponent size={20} color={'red'} text={'HelloWorld'} />
//Size must be one of 'small' or 'large' not the numeric value.

So my question is, what are the ways of handling this issue of using TypeScript (and tsx) written components in a non-TypeScript project?

There're some ways I've identified -

  • Using some parser for d.ts file
  • Creating a HoC for all the components
  • Writing propTypes along with interfaces for all the components manually.

Are there any other cleaner and less manual way?

like image 417
noob Avatar asked Jan 06 '19 09:01

noob


People also ask

Does TypeScript have PropTypes?

You can generate PropTypes from TypeScript type definitions using babel-plugin-typescript-to-proptypes . When you specify types for your props, the plugin converts those type definitions to PropTypes definitions. It will be compiled accordingly, thereby giving your React application type-checking powers during runtime.

Do you need React PropTypes with TypeScript?

Props are required in TypeScript In the prop-types package, all props are optional by default. To make a prop required, you will have to use . isRequired explicitly. With TypeScript, that is not the case.

Is PropTypes deprecated?

PropTypes is deprecated since React 15.5.


1 Answers

A perfect question! I'm looking into this exact problem myself right now.

First of all, I can agree that TypeScript is not a 100% replacement for PropTypes, because:

  1. If you are building a library and it's being consumed by a project in vanilla JavaScript, the typings could not help to detect all the problems.

  2. PropTypes are working dynamically at runtime, while TypeScript checks are only run statically.

  3. PropTypes could be used to get information about a component at runtime, while type definitions are lost at runtime.

My search showed me the following possibilities:

  • babel-plugin-typescript-to-proptypes

It allows to actually generate PropTypes during TypeScript compilation. It works as a plugin for Babel. The drawback is that you have to use Babel in order to utilize this functionality. Actually, I've posted a question: Using the plugin without Babel?, but I have my doubts that it could be possible.

  • prop-types-ts

As I can see from the documentation, this is not a fully compatible PropTypes generator, but instead a replacement, which uses it's own implementation for type checking at runtime. I would prefer my PropTypes to be fully compatible with the official implementation though.


You have to choose what are acceptable for you and what is your project's requirements are. If you are fine with using Babel I would recommend the first choice. However, if you only need to make sure that type checking is working at runtime, than second approach could be viable.

As for me, I think I will have to keep both TypeScript typings and manual PropTypes in sync for now, because I'm not using Babel and I don't really like a custom PropTypes implementation.

Maybe, one sunny day, we will find some resources to actually write our own PropTypes generator in our company and will share it with everyone.


Here's a typing trick that could be used to keep PropTypes in sync with typings:

import * as PropTypes from 'prop-types';
import React, {PureComponent} from 'react';


export interface IconProps {
  name: string;
}

export class Icon extends PureComponent<IconProps> {

  static propTypes: { [key in keyof IconProps]: any } = {
    name: PropTypes.string
  };

  render() {
    return <i className="dc-icon">{this.props.name}</i>;
  }

}

This will force propTypes object to has exactly the same properties that your props interface.

like image 70
Slava Fomin II Avatar answered Oct 06 '22 12:10

Slava Fomin II