17

I would like to create pluggable React components. Components are resolved by their class names, so I am naturally drawn to generics; but this doesn't seem to work.

class Div<P, S, C extends React.Component> extends React.Component<void, void> {

    render() {
        return (
            <div>
                <C /> // error: Cannot find name 'C'.
            </div>
        );
    }
}

Is there an alternative way to write pluggable TypeScript components?

0

2 Answers 2

37

The accepted answer for this question still stands, due to TypeScript types being erased, however as of Typescript 2.9, generic JSX components are supported

The example provided is:

class GenericComponent<P> extends React.Component<P> {
    internalProp: P;
}
type Props = { a: number; b: string; };

const x = <GenericComponent<Props> a={10} b="hi"/>; // OK
const y = <GenericComponent<Props> a={10} b={20} />; // Error

Just thought it worth mentioning for anyone who ends up here via the question title.

Sign up to request clarification or add additional context in comments.

1 Comment

What a weird example (I of course followed the link and saw that it's an official one). I really hope people don't start writing such things thinking that that's how it must be done.
12

This isn't possible to do using generics, though it's not clear why you would want to use generics for this problem rather than just providing the inner element using the normal props mechanism.

The reason is that types are erased, so you need to provide the class constructor to the class so that it has a reference to the value to instantiate in C. But there's no place other than the JSX props (or state or whatever you need to do) for you to pass in that value.

In other words, instead of writing

// not sure what you would expect the syntax to be?
const elem = <Div<Foo> ... />; 

You should write

const elem = <Div myChild={Foo} />

and consume it in your render as

const Child = this.props.myChild;
return <div><Child /></div>;

As an aside, the correct constraint is new() => React.Component rather than React.Component -- remember that the things you write in the JSX (<Div>, etc) are the constructors for classes, not the class instances.

1 Comment

Could you elaborate on what it means for a type to be erased? Are you talking about how the types disappear when the typescript code is compiled to javascript? (e.g., this answer?)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.