Skip to content
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

React 0.13 - Component vs ComponentClass #3978

Closed
tugend opened this issue Mar 27, 2015 · 8 comments
Closed

React 0.13 - Component vs ComponentClass #3978

tugend opened this issue Mar 27, 2015 · 8 comments

Comments

@tugend
Copy link

tugend commented Mar 27, 2015

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 }),
@vsiao
Copy link
Contributor

vsiao commented Mar 29, 2015

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

@tugend
Copy link
Author

tugend commented Mar 30, 2015

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. =)

@vsiao
Copy link
Contributor

vsiao commented Mar 30, 2015

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>

@tugend
Copy link
Author

tugend commented Mar 31, 2015

Well that worked! Thank you, you're awesome. ^_^

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

@vsiao
Copy link
Contributor

vsiao commented Mar 31, 2015

Great! I'm glad that worked out.

@flyon
Copy link

flyon commented Jun 4, 2015

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!

@OliverJAsh
Copy link
Contributor

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: microsoft/TypeScript#10603 (comment)

@orta
Copy link
Collaborator

orta commented Jun 7, 2021

Hi thread, we're moving DefinitelyTyped to use GitHub Discussions for conversations the @types modules in DefinitelyTyped.

To help with the transition, we're closing all issues which haven't had activity in the last 6 months, which includes this issue. If you think closing this issue is a mistake, please pop into the TypeScript Community Discord and mention the issue in the definitely-typed channel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants