Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type annotation for React Higher Order Component using TypeScript

I am writing a Higher Order Component for my React project using Typescript which is basically a function accepts a React component as an argument and return a new component that wraps around it.

Yet as it works as expected, TS is complaining that "Return type of exported function has or is using private name "Anonymous class".

Function in question:

export default function wrapperFunc <Props, State> (
    WrappedComponent: typeof React.Component,
) {
    return class extends React.Component<Props & State, {}> {
        public render() {
            return <WrappedComponent {...this.props} {...this.state} />;
        }
    };
}

The error is reasonable as the returning class of wrapper function is not exported and other module imports this function has no way of knowing what the return value would be. But I cannot declare the return class outside of this function as it requires to wrap a component pass to the outer function.

A trial with explicitly specifying return type typeof React.Component like below do suppress this error.

Function in question with explicit return type:

export default function wrapperFunc <Props, State> (
    WrappedComponent: typeof React.Component,
): typeof React.Component {                     // <== Added this
    return class extends React.Component<Props & State, {}> {
        public render() {
            return <WrappedComponent {...this.props} {...this.state} />;
        }
    };
}

However, I am not certain about validity of this approach. Is it considered a right approach for tackling this particular error in TypeScript? (Or am I creating unintended side effects elsewhere? Or any better way of doing such?)

(Edit) Change quoted code as per Daniel's suggestion.

like image 770
shuntksh Avatar asked Jan 06 '17 05:01

shuntksh


People also ask

Can you use hooks in higher-order components?

In a modern React world, everyone uses function components with React Hooks. However, the concept of higher-order components (HOC) is still applicable in a modern React world, because they can be used for class components and function components.

Is React memo a higher-order component?

React.memo is a higher order component. If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.

What is the higher-order component generally used for in React?

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React's compositional nature. Concretely, a higher-order component is a function that takes a component and returns a new component.


1 Answers

Type annotation for React Higher Order Component using TypeScript

The return type typeof React.Component is truthful, but not very helpful for users of the wrapped component. It discards information about what props the component accepts.

The React typings provide a handy type for this purpose, React.ComponentClass. It’s the type of a class, rather than the type of the component created from that class:

React.ComponentClass<Props>

(Note that the state type isn’t mentioned as it’s an internal detail).

In your case:

export default function wrapperFunc <Props, State, CompState> (
    WrappedComponent: typeof React.Component,
): React.ComponentClass<Props & State> {
    return class extends React.Component<Props & State, CompState> {
        public render() {
            return <WrappedComponent {...this.props} {...this.state} />;
        }
    };
}

However, you’re doing the same thing with the WrappedComponent parameter. Based on how you’re using it inside render, I’m guessing that it should also be declared:

WrappedComponent: React.ComponentClass<Props & State>,

But this is wild guess as I assume this is not the complete function (CompState isn’t used, and Props & State may as well be a single type parameter as it always appears in that combination).

like image 148
Daniel Earwicker Avatar answered Nov 25 '22 14:11

Daniel Earwicker