Create a TypeScript HOC (Higher Order Component) in React
You may have a number of custom HOC’s (higher order components) in your components deck, and now you’ve implemented TypeScript to your stack.
function youreAlwaysCoolHOC(ChildComp) {
return class Component extends React.Component {
state = {
areYouCool: false
};
handleClick = () => this.setState({ areYouCool: true });
render() {
return (
<>
<button onClick={this.handleClick}>Find yout if you're cool</button>
<ChildComp areYouCool={this.state.areYouCool} />
</>
);
}
};
}
All of sudden you see errors about your child component parameter is type any
implicitly.
Parameter 'ChildComp' implicitly has an 'any' type
Here’s how you define your component parameter type.
Answer: TypeScript interface React.ComponentType
I’ve created a new a HOC (higher order component) called youreAlwaysCoolHOC()
.
interface AwaysCoolStateProps {
areYouCool: boolean;
}
function youreAlwaysCoolHOC(ChildComp: React.ComponentType<any | string>) {
return class Component extends React.Component<{}, AwaysCoolStateProps> {
state = {
areYouCool: false
};
handleClick = () => this.setState({ areYouCool: true });
render() {
return (
<>
<button onClick={this.handleClick}>Find yout if you're cool</button>
<ChildComp areYouCool={this.state.areYouCool} />
</>
);
}
};
}
youreAlwaysCoolHOC()
will accept a parameter that should be a React component.
function youreAlwaysCoolHOC(ChildComp: React.ComponentType<any | string>) {}
I’ve also defined a variable ChildComp
as React.ComponentType
. This type interface will accept class components and functional components
.
Let’s take a closer look at what youreAlwaysCoolHOC()
does.
interface AwaysCoolStateProps {
areYouCool: boolean;
}
class Component extends React.Component<{}, AwaysCoolStateProps> {
state = {
areYouCool: false
};
handleClick = () => this.setState({ areYouCool: true });
render() {
return (
<>
<button onClick={this.handleClick}>Find yout if you're cool</button>
<ChildComp areYouCool={this.state.areYouCool} />
</>
);
}
};
youreAlwaysCoolHOC()
returns a new, and enhanced React component that displays a button for a user to click on.
It also passes the state value as a prop to the child component.
Here’s how to use the React HOC.
interface ContainerProps {
areYouCool: boolean;
}
const Container: React.SFC<ContainerProps> = props => (
<h1>{props.areYouCool ? "Heck yes I'm cool! :)" : ":("}</h1>
);
const App = youreAlwaysCoolHOC(Container);
To accept the React prop that youreAlwaysCoolHOC()
provides, I must extend the React component interface. That’s where ContainerProps
comes into play.
And that’s it!
Conclusion
Use the type interface React.ComponentType
to define the component parameter in your custom React HOC (higher order component).
Full code example
interface ContainerProps {
areYouCool: boolean;
}
interface AwaysCoolStateProps {
areYouCool: boolean;
}
function youreAlwaysCoolHOC(ChildComp: React.ComponentType<any | string>) {
return class Component extends React.Component<{}, AwaysCoolStateProps> {
state = {
areYouCool: false
};
handleClick = () => this.setState({ areYouCool: true });
render() {
return (
<>
<button onClick={this.handleClick}>Find yout if you're cool</button>
<ChildComp areYouCool={this.state.areYouCool} />
</>
);
}
};
}
const Container: React.SFC<ContainerProps> = props => (
<h1>{props.areYouCool ? "Heck yes I'm cool! :)" : ":("}</h1>
);
const App = youreAlwaysCoolHOC(Container);
I like to tweet about React and post helpful code snippets. Follow me there if you would like some too!