A common pattern in TypeScript is to create type helpers that allow you to extract types from things that are not types.

Here we've created a PropsFrom type helper.


type PropsFrom<TComponent> = any

const props: PropsFrom<typeof MyComponent> = {

enabled: true,

}


Currently what we want it to do is to return the props. Here it would return enabled: boolean if we put MyComponent in there.


const MyComponent = (props: { enabled: boolean }) => {

return null

}


So let's see how we do that. If we go TComponent extends a React.FC which is a functional component, then we can actually add a generic there and we can say infer the Props.

Then we can return the Props and otherwise, because this is a ternary and it needs to return something, we say never.


type PropsFrom<TComponent> = TComponent extends React.FC<infer Props>

? Props

: never


And now if we PropsFrom MyComponent we get enabled: boolean.

So for instance if I go and change the enabled prop in MyComponent to true and then set enabled in our props object to be false, then that's. going to fail because it's expecting true.

But what if you want to feed multiple types of things into this helper? For instance what if we also wanted to derive the prop types of a class component instead of a functional component.


class MyOtherComponent extends React.Component<{

enabled: boolean;

}> {}

...

const props: PropsFrom<MyOtherComponent> = {

enabled: true,

};


To do this we'll need to add another layer to the PropsFrom ternary.

So here in the ternary, for the else case we'll check if the TComponent is a React.Component which is the type of a class component. From that we'll infer its Props.


type PropsFrom<TComponent> = TComponent extends React.FC<infer Props>

? Props

: TComponent extends React.Component<infer Props>

? Props

: never


So this now is working both with react functional components and class components.