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
React.ComponentClass
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>;
...
}
I'm still having this error with ts 2.9.1. What is actually the work around for this?
Most helpful comment
I'm still having this error with ts 2.9.1. What is actually the work around for this?