Home > database >  How to specify type of a React class component with static props
How to specify type of a React class component with static props

Time:12-30

Consider we have a simple React component with a static property like meta here:

// RectTool.tsx

class Rect extends React.PureComponent
    static meta = {
        icon: <AnotherComponent />,
        initial: {
            width: 50,
            height: 50,
        },
    };

    render() {
        return (
            <div>Hello World</div>
        );
    }
}

Then in another component we're referencing that component as a prop:

// DesignerUI.tsx

<Designer
    tools={[Rect]}
/>

How do we define the type for the tools prop in <Designer /> so that typescript would be happy. What I'm doing right now is:

// DesignerUI.tsx

interface Props {
  tools: Array<
    React.PureComponent & {
      meta: {
        icon: JSX.Element;
        initial: { width: number; height: number; strokeWidth: number };
      };
    }
  >;
}

And typescript gives me this error:

Type 'typeof Rect' is not assignable to type 'PureComponent<{}, {}, any> & { meta: { icon: Element; initial: { width: number; height: number; strokeWidth: number; }; }; }'.
  Type 'typeof Rect' is missing the following properties from type 'PureComponent<{}, {}, any>': context, setState, forceUpdate, render, and 3 more.ts(2322)

CodePudding user response:

There is no reason that a tool needs to be a React.PureComponent specifically. It seems like your requirements for your tool objects should be:

  1. It can be called using JSX as <Rect/> with no props.
  2. It has a meta property with the appropriate values.

I would suggest that you define the type for your ToolMeta at the top level and use it in both the Rect and the Designer. You've already got a mismatch between initialValues in one place and initial in another. A good ToolMeta type can prevent this sort of mistake.

Personally I prefer to keep most interfaces one-level deep and break out sub-properties into their own named types.

interface ToolInitialValues {
    width: number;
    height: number;
    strokeWidth?: number;
}

interface ToolMeta {
    icon: JSX.Element;
    initialValues: ToolInitialValues;
}

We can use this type in the Rect to get type-checking on the meta object:

class Rect extends React.PureComponent {
    static meta: ToolMeta = {

Your tool components must have { meta: ToolMeta } to meet condition #2. For condition #1, you'll want to use the React.ComponentType type which is the type for a function component or class component. Your current React.PureComponent type actually refers to the instance rather than the class itself.

interface Props {
  tools: Array<
    React.ComponentType & { meta: ToolMeta }
  >;
}

Typescript Playground Link

  • Related