1

I have a question regarding JSX and Typescript integration. Given the following code:

interface Props {
    component?: React.ReactType
}

class MyComponent extends React.Component<Props, void> {
    render() {
      var Comp = this.props.component
      return (<Comp></Comp>)
    }
}

I get: JSX element type 'Comp' does not have any construct or call signatures.

How do I fix this? Similar code works fine in Javascript where component has prop validator elementType from react-prop-types, so it could be either a string or component class.

3 Answers 3

1

If you take a look at the definition of react type in typing, you will find that you have a union type of 3 different types, one of which is a string. That's why you had such a problem. Try replacing React.ReactType with React.ComponentClass.

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

3 Comments

But I want a string too, it is allowed in react javascript.
@user3250645 then you shouldn't use typescript. There are a lot of correct programs which you can't type. It's a trade-off, you loose some freedom of expression but gain more safety.
the issue has nothing to do with typescript as a language. Obviously its type system is flexible enough to express what is needed (i.e. ReactType). The issue is that JSX parser in typescript expects JSX.Element class and I don't know that how bridge between ReactType (which may mean simple string) and JSX.Element (which expects React.Component). I'm sure it's possible.
1

How are you creating the component that you're passing in? If you create it like this it should work:

interface MyProps {
    component?: React.ReactType;
}

class TestComponent extends React.Component<void, void> {
    render() {
        return <div>Test</div>;
    }
}

class MyComponent extends React.Component<MyProps, void> {
    render() {
        const Comp = this.props.component
        return (<Comp/>);
    }
}


class Parent extends React.Component<{}, {}> {
    render() {
       return (
          <MyComponent component={TestComponent}></MyComponent>
       )
    }
}

You could also pass an html element as a string (e.g. "div"), but I'm not sure if that's what you wanted to do.

Comments

0

I will give you an example using the functional component:

type YourProps = { count: number };
type Props = {
  component: ElementType<YourProps>
}

function Parent({component}: Props): ReactElement {

  return (
    <>
      {React.createElement(component, {count: 1})}
    </>
  );
}

function Child({count}: YourProps) {
  return <>Count: {count}</>
}

function Root() {
  return <><Parent component={Child}/></>
}

In this case you will delegate the construction of element for the Parent component and it would natively create by using React API - createElement and passing props into it.

Comments

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.