Hi.
I might be mistaken, but shouldn麓t class Component implement ComponentClass?
Here's an example, it compiles using TS 1.4, and runs as expected with React 0.13.1 - but if I replace any with P I get ""Argument of type 'typeof Button is not assignable to type 'string'"" because the overload on createElement cannot find a better match.
interface P {
happy: boolean
}
class Button extends React.Component<any, {}> {
}
React.createElement(Button, { happy: true }),
ComponentClass is the interface for the Component object (the interface for static properties on Component, in other words). To say class Component implements ComponentClass means that every _instance_ of Component must have the properties defined by the ComponentClass interface.
May I recommend creating factories? I think you'll find the type errors to be a little more useful. eg:
var button = React.createFactory(Button);
button({ happy: 3 });
which should give you
TS2345: Argument of type '{ happy: number; }' is not assignable to parameter of type 'P'.
Types of property 'happy' are incompatible.
Type 'number' is not assignable to type 'boolean'.
Thank you for the reply! =)
I had misunderstood the relation. I fear the problem remains though.
I tried to use factories, here is a more condensed example of what I'm guessing is the same underlying problem. To my understanding, createFactory does not actually recognize Component, only string, ComponentClass and ClassicComponent. Shouldn't createElement, and createFactory be overloaded to also take Component then?
The following will yield the same error, 'Argument of type "typeof Button' is not assignable to parameter of type 'string'"
interface P
{
color?: string
}
class Button extends React.Component<P, {}>
{
static defaultProps =
{
color: null,
}
render()
{
return React.DOM.div();
}
}
var button = React.createFactory(Button);
The error does not occur if I remove the optional modifier on color, or if I use createFactory
,
but I think it ought to work? Your answer is very much appriciated. =)
You need to explicitly type-annotate defaultProps:
static defaultProps: P =
I think that will fix it. btw, here's a handy reference for React types:
ComponentClass<P> --> --> ReactElement<P> --> --> Component<P, S>
ClassicComponentClass<P> --> React.createElement --> ClassicElement<P> --> React.render --> ClassicComponent<P, S>
string --> --> DOMElement<P> --> --> DOMComponent<P>
Well that worked! Thank you, you're awesome. ^_^
Great! I'm glad that worked out.
great, I couldn't figure out how to use defaultProps, but making it a static property and setting its type fixed it. Thank you for the clarification on the react types too, very helpful!
Here is what I am doing to get my static properties, as defined by ComponentClass, type checking for React components:
// error as expected, displayName should be string
const ReactComponent: ComponentClass<any> = class extends Component<any, any> {
static displayName = 1
render() {
return <div>{this.props.name}</div>
}
};
I think in the ideal case there would be no ComponentClass interface and only a Component class, but I believe we are waiting for a feature to be implemented in TypeScript (static properties on abstract classes). More detail: https://github.com/Microsoft/TypeScript/issues/10603#issuecomment-306232573
Most helpful comment
ComponentClassis the interface for theComponentobject (the interface for static properties onComponent, in other words). To sayclass Component implements ComponentClassmeans that every _instance_ ofComponentmust have the properties defined by theComponentClassinterface.May I recommend creating factories? I think you'll find the type errors to be a little more useful. eg:
which should give you