Typescript & React
How to type React Higher Order Components (HOC)
See this great article: React Higher-Order Components in TypeScript made simple
How to type it:
const myHoc = <P extends Props>(
Component: React.ComponentType<P & myHocProps>
): React.ComponentClass<P> => {
return class extends React.Component<P> {
...
}
}Note: The type React.Component is an instance of the component. On the other hand React.ComponentType is the actual subclass of React.Component.
Conditional React props with TypeScript (via discriminated union)
Using TypeScript to only allow a React prop to be set when another has a specific value
Taken from this article.
A discriminated union plus the never type does the trick here:
interface CommonProps {
children: React.ReactNode
// ...other props that always exist
}
type TruncateProps =
| { truncate?: false; showExpanded?: never }
| { truncate: true; showExpanded?: boolean }
type Props = CommonProps & TruncateProps
const Text = ({ children, showExpanded, truncate }: Props) => {
// Both truncate & showExpanded will be of
// the type `boolean | undefined`
}
Text({ children: 'text', showExpanded: true, truncate: true }) // works
Text({ children: 'text', truncate: false }) // works
Text({ children: 'text', showExpanded: true, truncate: false }) // throws errorSee this TS playground.
Update: Consider using undefined type instead of never for the same behavior (as described here):
Related example:
If error is undefined there’s a value. If it’s defined, its an error without a value:
type Result<T> = { error?: undefined, value: T } | { error: Error };
function test(x: Result<number>) {
if (!x.error) {
x.value; // number
}
else {
x.error.message; // string
}
}
test({ value: 10 });
test({ error: new Error("boom") });Discuss on Twitter ● Improve this article: Edit on GitHub