Michael Durrant
Michael Durrant

Reputation: 96454

How to use PropTypes with Typescript in React

I am trying to use PropTypes with Typescript but getting errors:

Without typescript I was able to use:

class TodoFilterItem extends Component {
  constructor (props) {
    super(props);

and then at the bottom

TodoFilterItem.propTypes = {
  name: PropTypes.string,
  filter: PropTypes.string,
  filterTodos: PropTypes.any
}

and that worked for just having PropTypes (i.e. no typescript).

However when I add Typescript and I have

class TodoFilterItem extends Component<ITodoFilterItem> {
  constructor (props:ITodoFilterItem) {
    super(props);
    ...

I have props as an interface like this:

interface ITodoFilterItem  {
  filter: string,
  name: string,
  filterTodos: any
}

and I use the same propTypes:

TodoFilterItem.propTypes = {
  filter: PropTypes.string,
  name: PropTypes.string,
  filterTodos: PropTypes.any
}

I get an error

Property 'propTypes' does not exist on type 'typeof import("/my_adrs/node_modules/@types/prop-types/index")'.  

How to address this and be able to use PropTypes with Typescript in React ?

Upvotes: 2

Views: 4652

Answers (1)

Bens Steves
Bens Steves

Reputation: 2849

PropTypes are separate from Typescript. To reuse your propTypes you have to convert it to an interface or type.

This

TodoFilterItem.propTypes = {
  filter: PropTypes.string,
  name: PropTypes.string,
  filterTodos: PropTypes.any
}

becomes

interface ITodoFilterItem {
  filter: string;
  name: string;
  filterTodos: any; 
}

Using that interface is simple, you replace TodoFilterItemProps with ITodoFilterItem.

The convention is to name your component props IProps. Putting that together your component now looks like:

interface IProps { 
 name: string;
 filter: string;
 filterTodos: any; 
}

class TodoFilterItem extends Component<IProps> {
  constructor (props:IProps) {
    super(props);
    ...

Note on any

Try to avoid typing to any. any type is the same has untyped. I imagine filterTodos is an array of todos. If that's the case you can create a type for todo call it

type Todo = { ...properties of a todo } 

then type filterTodos to be an array of Todo which would look like this:

type Todo = { 
  name: string,
  status: 'not started' | 'in progress' | 'done'
}

interface IProps { 
  filter: string;
  name: string;
  filterTodos: Todo[]; 
}

Upvotes: 4

Related Questions