diff --git a/react/react-tests.ts b/react/react-tests.ts index 5a20d51f8..adf2e251e 100644 --- a/react/react-tests.ts +++ b/react/react-tests.ts @@ -24,7 +24,6 @@ interface Props extends React.Props { hello: string; world?: string; foo: number; - bar: boolean; } interface State { @@ -48,8 +47,7 @@ var props: Props = { key: 42, ref: "myComponent42", hello: "world", - foo: 42, - bar: true + foo: 42 }; var container: Element; @@ -61,11 +59,10 @@ var container: Element; var ClassicComponent: React.ClassicComponentClass = React.createClass({ getDefaultProps() { - return { + return { hello: undefined, world: "peace", - foo: undefined, - bar: undefined, + foo: undefined }; }, getInitialState() { @@ -87,7 +84,7 @@ var ClassicComponent: React.ClassicComponentClass = }); class ModernComponent extends React.Component - implements React.ChildContextProvider { + implements MyComponent, React.ChildContextProvider { static propTypes: React.ValidationMap = { foo: React.PropTypes.number @@ -101,8 +98,6 @@ class ModernComponent extends React.Component someOtherValue: React.PropTypes.string } - static defaultProps: Props; - context: Context; getChildContext() { @@ -117,12 +112,14 @@ class ModernComponent extends React.Component } reset() { + this._myComponent.reset(); this.setState({ inputValue: this.context.someValue, seconds: this.props.foo }); } + private _myComponent: MyComponent; private _input: HTMLInputElement; render() { @@ -134,12 +131,32 @@ class ModernComponent extends React.Component } } +interface SCProps extends React.Props<{}> { + foo?: number; +} + +var StatelessComponent = (props: SCProps) => { + return React.DOM.div(null, props.foo); +}; + +// Must explicitly type-annotate to add defaultProps/contextTypes +var StatelessComponent2: React.StatelessComponent = + (props: SCProps) => React.DOM.div(null, props.foo); +StatelessComponent2.defaultProps = { + foo: 42 +}; + // React.createFactory var factory: React.Factory = React.createFactory(ModernComponent); var factoryElement: React.ReactElement = factory(props); +var statelessFactory: React.Factory = + React.createFactory(StatelessComponent); +var statelessElement: React.ReactElement = + statelessFactory(props); + var classicFactory: React.ClassicFactory = React.createFactory(ClassicComponent); var classicFactoryElement: React.ClassicElement = @@ -153,6 +170,8 @@ var domFactoryElement: React.DOMElement = // React.createElement var element: React.ReactElement = React.createElement(ModernComponent, props); +var statelessElement: React.ReactElement = + React.createElement(StatelessComponent, props); var classicElement: React.ClassicElement = React.createElement(ClassicComponent, props); var domElement: React.ReactHTMLElement = @@ -161,6 +180,8 @@ var domElement: React.ReactHTMLElement = // React.cloneElement var clonedElement: React.ReactElement = React.cloneElement(element, props); +var clonedStatelessElement: React.ReactElement = + React.cloneElement(statelessElement, props); var clonedClassicElement: React.ClassicElement = React.cloneElement(classicElement, props); var clonedDOMElement: React.ReactHTMLElement = @@ -215,6 +236,36 @@ classicComponent.replaceState({ inputValue: "???", seconds: 60 }); var myComponent = component; myComponent.reset(); +// +// Refs +// NB: to infer the correct type for callback refs, your component's Props +// interface must extend React.Props where T is your component type (or +// an interface that it implements). +// -------------------------------------------------------------------------- + +interface RCProps extends React.Props { +} + +class RefComponent extends React.Component { + static create = React.createFactory(RefComponent); + refMethod() { + } +} + +var componentRef: RefComponent; +RefComponent.create({ ref: "componentRef" }); +// type of c should be inferred +RefComponent.create({ ref: c => componentRef = c }); +componentRef.refMethod(); + +var domNodeRef: Element; +React.DOM.div({ ref: "domRef" }); +// type of node should be inferred +React.DOM.div({ ref: node => domNodeRef = node }); + +var inputNodeRef: HTMLInputElement; +React.DOM.input({ ref: node => inputNodeRef = node }); + // // Attributes // -------------------------------------------------------------------------- diff --git a/react/react.d.ts b/react/react.d.ts index cb8ff8ed1..7801dd51e 100644 --- a/react/react.d.ts +++ b/react/react.d.ts @@ -8,21 +8,21 @@ declare namespace __React { // React Elements // ---------------------------------------------------------------------- - type ReactType = ComponentClass | string; + type ReactType = string | ComponentClass | StatelessComponent; - interface ReactElement

{ - type: string | ComponentClass

; + interface ReactElement

> { + type: string | ComponentClass

| StatelessComponent

; props: P; key: string | number; ref: string | ((component: Component | Element) => any); } interface ClassicElement

extends ReactElement

{ - type: string | ClassicComponentClass

; + type: ClassicComponentClass

; ref: string | ((component: ClassicComponent) => any); } - interface DOMElement

extends ReactElement

{ + interface DOMElement

> extends ReactElement

{ type: string; ref: string | ((element: Element) => any); } @@ -47,7 +47,7 @@ declare namespace __React { (props?: P, ...children: ReactNode[]): ClassicElement

; } - interface DOMFactory

extends ClassicFactory

{ + interface DOMFactory

> extends Factory

{ (props?: P, ...children: ReactNode[]): DOMElement

; } @@ -73,19 +73,19 @@ declare namespace __React { function createClass(spec: ComponentSpec): ClassicComponentClass

; function createFactory

(type: string): DOMFactory

; - function createFactory

(type: ClassicComponentClass

| string): ClassicFactory

; - function createFactory

(type: ComponentClass

): Factory

; + function createFactory

(type: ClassicComponentClass

): ClassicFactory

; + function createFactory

(type: ComponentClass

| StatelessComponent

): Factory

; function createElement

( type: string, props?: P, ...children: ReactNode[]): DOMElement

; function createElement

( - type: ClassicComponentClass

| string, + type: ClassicComponentClass

, props?: P, ...children: ReactNode[]): ClassicElement

; function createElement

( - type: ComponentClass

, + type: ComponentClass

| StatelessComponent

, props?: P, ...children: ReactNode[]): ReactElement

; @@ -116,11 +116,6 @@ declare namespace __React { // Base component for plain JS classes class Component implements ComponentLifecycle { - static propTypes: ValidationMap; - static contextTypes: ValidationMap; - static childContextTypes: ValidationMap; - static defaultProps: Props; - constructor(props?: P, context?: any); setState(f: (prevState: S, props: P) => S, callback?: () => any): void; setState(state: S, callback?: () => any): void; @@ -148,6 +143,13 @@ declare namespace __React { // Class Interfaces // ---------------------------------------------------------------------- + interface StatelessComponent

{ + (props?: P, context?: any): ReactElement; + propTypes?: ValidationMap

; + contextTypes?: ValidationMap; + defaultProps?: P; + } + interface ComponentClass

{ new(props?: P, context?: any): Component; propTypes?: ValidationMap

; @@ -325,6 +327,7 @@ declare namespace __React { defaultChecked?: boolean; defaultValue?: string | string[]; } + interface SVGProps extends SVGAttributes, Props { } @@ -1001,6 +1004,7 @@ declare namespace JSX { defs: React.SVGProps; ellipse: React.SVGProps; g: React.SVGProps; + image: React.SVGProps; line: React.SVGProps; linearGradient: React.SVGProps; mask: React.SVGProps;