reactjs / react-future

Specs & docs for potential future and experimental React APIs and JavaScript syntax.
2.82k stars 113 forks source link

Small syntax updates to Classes.js #16

Closed cpojer closed 10 years ago

cpojer commented 10 years ago

I'm just playing a little bit with this and there are some interesting syntax bits to consider here.

sophiebits commented 10 years ago

I think the idea with defaultProps was that it would get merged in before the component is instantiated, so props.width would never be null, even though you might not pass width to createElement.

cpojer commented 10 years ago

that's a good point. I saw the prop type definition as the external interface to the React component, something like Button<props as defined in the class>({width: …}) where, if default props are specified, they must then be nullable to not cause the static analysis to yell at you. Essentially we end up with two different interfaces for external and internal props, how will we solve this? If width is nullable, the external prop interface is correct (you don't need to pass width at all), but if the internal interface is also nullable, it will require you to null check the prop on every use. That's not good. If it isn't nullable, it must always be passed on instantiation, defeating the purpose of default props.

It almost sounds as if the props type specified on the class and the types for defaultProps should be merged and make nullable fields non-nullable, something like this:

props: {
  height: number;
  width: ?number;
}

static defaultProps: {
  width: 100
}

render(props: InternalProps) {

}

where InternalProps is defined as:

{
  height: number;
  width: number;
}

based on merging the type props and the inferred types of defaultProps. Will Flow and/or TypeScript support something smart like this?

sebmarkbage commented 10 years ago

It's never null. It can be undefined.

There are three types in play:

1) The explicit internal type of this.props which is also the same as element.props. 2) The type of the objects that you pass into React.createElement(). 3) The type of the default props.

2 and 3) can be inferred. They don't need explicit type signature. The merge of 2 and 3 must result in an object that satisfies 1.

As for the semi-colons. I'm being intentional controversial to challenge the idea that we need them, and TypeScript's choice of using semi-colons is the wrong choice and it should be changed as part of the standardization process.