How to import a React proptypes typed component as type any into a React Typescript component

Viewed 1821

We have quite a big component library done in proptypes, and we are moving to typescript.

So when I was moving a .jsx component to be a .tsx component an imported .jsx component suddenly started throwing typing errors, there is nothing currently wrong with the imported component and I can't just rewrite it typescript as it is used everywhere and it would be more effort at the moment than worth.

to get around this I did as follows (lots of intervening code removed)

import MyReactComponent from 'path/to/component';

const FixedMyReactComponent: any = MyReactComponent;

return <FixedMyReactComponent/>

it works, my errors went away, but I find this to be irritating, I would instead like not to have to make a FixedMyReactComponent and set a type for it locally, and (as I already said) I don't want to put in the time right now to fix the fact that typescript isn't understanding my component, so instead I would like to find some way to globally tell typescript ignore type errors you get from a js / jsx and only report errors from .ts / .tsx.

I suppose it would be something like

declare module '*.jsx' {
  var _: React.Component<any, any>;
  export default _;
}

but that doesn't seem to have the effect I want.

2 Answers

move your proptypes to a type then you can just type your component.

import { FC } from 'react'

type FixedMyReactComponentProps = {
  id: string;
  name: string;
}

const FixedMyReactComponent: FC<FixedMyReactComponentProps> = ({name, id}) => {
...
}

But if you must type it as any. You declare the return type:

const FixedMyReactComponent = (): any => {
  ...
}

If you are time-constrained in doing the work now you could use // @ts-nocheck (added in TypeScript v3.7 for this exact use case) at the top of all your newly created .ts?(x) files and gradually remove them over time. This will type check NOTHING basically treating the file as javascript while exporting whatever explicit or implicit types are defined in the file. You may also want to loosen the compilerOptions something like this until you can tighten them later on.


If you do have some time to complete the conversion you could look into using the react-javascript-to-typescript-transform npm package from lyft. It is deprecated but seems to get the job done, at least for the prop-type to type conversions.

Starting with a simple js prototype example from react.

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

Install the module...

npm install -g react-js-to-ts

Run this command to convert all js files to ts.

react-js-to-ts ./**/*.js

The package then replaces all files from js with prop-types into .tsx with prop interfaces.

type GreetingProps = {
  name?: string
};
class Greeting extends React.Component<GreetingProps, {}> {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

Works for functional components and class components. I am not sure how this behaves with state types or other non-typed code you may have in your component but this would be a good step forward. The state could easily be typed as any for the time being anyway. Also not sure how well this package performs with complex prototypes like PropTypes.shape and PropTypes.arrayOf.

If I were you I would verify all the changes, but any conversion errors should be very apparent via type errors. No need to use a fake js to ts component conversions. Even after running this code, if you run into too many type errors you can turn off strict mode and even add // @ts-nocheck where needed until your team has the bandwidth to address the bad types.

Honestly, I think this is the best approach, any other way of trying to trick the typescript compiler is gonna be more difficult and hacky than this or provide inconsistent types from your original prototype definitions.

Related