Skip to content

JSX: Typing both stateless component and component class in react component property gives error #8657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
asvetliakov opened this issue May 18, 2016 · 2 comments · Fixed by #8674
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue Help Wanted You can do this

Comments

@asvetliakov
Copy link

asvetliakov commented May 18, 2016

I need to type both stateless component and classic component in single component property:

TypeScript Version:
1.8.10/1.9.0-dev.20160518-1.0

Code

// A self-contained demonstration of the problem follows...
// Ideally:
interface ComponentProps {
   ButtonComponent: React.StatelessComponent<any> | React.ComponentClass<any>;
  ...
}

class MyComponent extends React.Component<ComponentProps, {}> {
  render() {
    const { ButtonComponent } = this.props;
    const someProps = {};
    const button = <ButtonComponent {...someProps}/>
    return (<div>{button}</div>);
  }
}

// Ideal usage

<MyComponent ButtonComponent={() => <button>test</button>}/>

class MyButtonComponent extends React.Component<{},{}> {
...
}

<MyComponent ButtonComponent={MyButtonComponent} />

Expected behavior:
Compiles successfully

Actual behavior:
Throws error: "JSX Element type ButtonComponent doesn't have any construct or call signatures"
It works If i change definition of ButtonComponent to just solo React.StatelessComponent or
React.ComponentClass

@evansb
Copy link
Contributor

evansb commented May 18, 2016

StatelessComponent has no construct signature but no call signature.
ComponentClass has construct signature but no call signature.

When both types are united, what we get is a type with no construct or call signature.
Whenever a React component is instantiated, first the element instance type will be checked for any construct signatures, then call signatures. (See getJsxElementInstanceType in checker.ts).

One possible fix is to handle union types separately here by recursively checks for construct/call signature.

interface StatelessComponent<P> {
        (props?: P, context?: any): ReactElement<any>;
...
}

interface ComponentClass<P> {
        new(props?: P, context?: any): Component<P, any>;
...
 }

evansb added a commit to evansb/TypeScript that referenced this issue May 19, 2016
mhegazy added a commit that referenced this issue May 19, 2016
 Fixes #8657: Handles union typed React component.
@mhegazy mhegazy added the Fixed A PR has been merged for this issue label May 19, 2016
@mhegazy mhegazy added this to the TypeScript 2.0 milestone May 19, 2016
@mhegazy mhegazy added Bug A bug in TypeScript Help Wanted You can do this labels May 19, 2016
@oesile
Copy link

oesile commented Jun 9, 2018

I'm still having this error with ts 2.9.1. What is actually the work around for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue Help Wanted You can do this
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants