Reputation: 6814
Using TypeScript 2.8 new conditional generic type feature, is it possible to extract the TProps
of a React.ComponentType<TProps>
component? I want a type that can either work on the ComponentType
or the TProps
itself, so you can - as a developer - pass either of both:
For example:
interface TestProps {
foo: string;
}
const TestComponent extends React.Component<TestProps, {}> {
render() { return null; }
}
// now I need to create a type using conditional types so that
// I can pass either the component or the props and always get the
// TProps type back
type ExtractProps<TComponentOrTProps> = /* ?? how to do it? */
type a = ExtractProps<TestComponent> // type a should be TestProps
type b = ExtractProps<TestProps> // type b should also be TestProps
Is this possible, and can anybody provide a solution?
Upvotes: 46
Views: 32213
Reputation: 92210
There's a built-in helper for that
type AnyCompProps = React.ComponentProps<typeof AnyComp>
And it also works for native DOM elements:
type DivProps = React.ComponentProps<"div">
https://stackoverflow.com/a/55005902/82609
Upvotes: 134
Reputation: 1281
I'd suggest to use React.ComponentType
, because it will also include functional components:
type ExtractProps<TComponentOrTProps> =
TComponentOrTProps extends React.ComponentType<infer TProps>
? TProps
: TComponentOrTProps;
Upvotes: 11
Reputation: 250366
It's a pretty straight forward application of conditional types and their inference behavior (using the infer
keyword)
interface TestProps {
foo: string;
}
class TestComponent extends React.Component<TestProps, {}> {
render() { return null; }
}
type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends React.Component<infer TProps, any> ? TProps : TComponentOrTProps;
type a = ExtractProps<TestComponent> // type a is TestProps
type b = ExtractProps<TestProps> // type b is TestProps
Upvotes: 5