Definitelytyped: React 0.13 - Component vs ComponentClass

Created on 27 Mar 2015  路  7Comments  路  Source: DefinitelyTyped/DefinitelyTyped

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 }),

Most helpful comment

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'.

All 7 comments

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. ^_^

https://www.youtube.com/watch?v=2bCXuClg0oM

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JWT
svipas picture svipas  路  3Comments

csharpner picture csharpner  路  3Comments

JudeAlquiza picture JudeAlquiza  路  3Comments

stevermeister picture stevermeister  路  3Comments

lilling picture lilling  路  3Comments