Blog

October 07, 2019 by Manuel

React TypeScript and Prop-Types

TypeScript and Prop-Types are both used to type properties of a react component. Often you will see people using one over another but not both together. Though these systems are handling different use-cases and using both can be efficient as well as beneficial.

TypeScript helps you when developing since it is checking types at compile time. This means while you are developing in your code editor you will get hints when you add a property to your react component with a wrong type.

In the following example we use a component called TemplateComponent and set a property called foo to which we pass a number variable 2. As you can see we get some fancy TypeScript warnings that lets us know that the variable foo is a string and we cannot pass a number to it.

TypeScript warnings example

In contrast prop-types will be checked during runtime, which can be helpful expecially in cases where you deal with data from external sources. Using prop-types you would gain helpful debugging information.

Since both approaches can help us in different ways, it is a good idea to use both. Of course it would be tedious to type our props two times. Luckily you can easily use InferProps in order to use the prop-types also for TypeScript. See example below:

import React from 'react';
import PropTypes, {InferProps} from 'prop-types';

function ColHalf(props: InferProps<typeof ColHalf.propTypes>): JSX.Element {
  const {children} = props;
  return <div className="newscol col half">{children}</div>;
}

ColHalf.propTypes = {
  children: PropTypes.node.isRequired,
  foo: PropTypes.string,
  bar: PropTypes.number
};

ColHalf.displayName = 'ColHalf';
export default ColHalf;

So you can write your typings for component props with prop-types and then infer those for TypeScript.

Combine TypeScript and Prop-Types

In case you want to combine inferred prop-types and TypeScript types, you could do this as follows:

import React from 'react';
import PropTypes, {InferProps} from 'prop-types';

type Props = {
  // has exactly three ReactNodes
  components: [
    React.ReactNode,
    React.ReactNode,
    React.ReactNode
  ];
};

function ColOneThird(props: InferredProps & Props): JSX.Element {
  const {components} = props;

  // EXAMPLE - Replace with your own
  return (
    <>
      <div className="col one_third">{components[0]}</div>
      <div className="col one_third" />
      <div className="col one_third" />
      <div className="cleaner" />
    </>
  );
}

type InferredProps = InferProps<typeof ColOneThird.propTypes>;
ColOneThird.propTypes = {
  foo: string
};

ColOneThird.displayName = 'ColOneThird';
export default ColOneThird;

You would define some TypeScript props as well as some inferred prop-types. Your can combine them using & as in ...(props: InferredProps & Props).