diff --git a/react-redux/react-redux-tests.tsx b/react-redux/react-redux-tests.tsx index 3ebf6ae539..d2f60fc5d9 100644 --- a/react-redux/react-redux-tests.tsx +++ b/react-redux/react-redux-tests.tsx @@ -10,7 +10,7 @@ import { Component, ReactElement } from 'react'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { Router, RouterState } from 'react-router'; -import { Store, Dispatch, bindActionCreators } from 'redux'; +import { Store, Dispatch, bindActionCreators, Action } from 'redux'; import { connect, Provider } from 'react-redux'; import objectAssign = require('object-assign'); @@ -20,11 +20,17 @@ import objectAssign = require('object-assign'); // interface CounterState { - counter: number; + counter: number } -declare var increment: Function; -class Counter extends Component { +declare var increment: () => Action + +interface CounterProps { + value: number, + onIncrement: Function +} + +class CounterAny extends Component { render() { return ( + ); + } +} function mapStateToProps(state: CounterState) { return { value: state.counter @@ -41,7 +56,7 @@ function mapStateToProps(state: CounterState) { } // Which action creators does it want to receive by props? -function mapDispatchToProps(dispatch: Dispatch) { +function mapDispatchToProps(dispatch: Dispatch) { return { onIncrement: () => dispatch(increment()) }; @@ -50,12 +65,13 @@ function mapDispatchToProps(dispatch: Dispatch) { connect( mapStateToProps, mapDispatchToProps -)(Counter); - +)(CounterAny); @connect(mapStateToProps) class CounterContainer extends Component { - + render() { + return + } } // Ensure connect's first two arguments can be replaced by wrapper functions @@ -87,6 +103,12 @@ connect( { pure: true } )(Counter); +@connect(mapStateToProps, mapDispatchToProps) +class CounterDispatchContainer extends Component { + render() { + return + } +} class App extends Component { render(): JSX.Element { diff --git a/react-redux/react-redux.d.ts b/react-redux/react-redux.d.ts index cf203d2368..f1a6657cb8 100644 --- a/react-redux/react-redux.d.ts +++ b/react-redux/react-redux.d.ts @@ -14,51 +14,72 @@ declare namespace ReactRedux { type Dispatch = Redux.Dispatch; type ActionCreator = Redux.ActionCreator; - interface ComponentDecorator { - (component: ComponentClass|StatelessComponent): ComponentClass; + + interface ComponentConstructor extends __React.ComponentLifecycle { + new(props?: P, context?: S) : void; + } + + interface ComponentClassDecorator { + (component: ComponentConstructor | ComponentClass | StatelessComponent): ComponentClass; + } + + interface ComponentDecorator { + (constructor: ComponentConstructor): void; } /** - * Decorator that infers the type from the original component - * - * Can't use the above decorator because it would default the type to {} - */ + * Decorator that infers the type from the original component + * + * Can't use the above decorator because it would default the type to {} + */ export interface InferableComponentDecorator { - |StatelessComponent

)>(component: TComponentConstruct): TComponentConstruct; + | StatelessComponent

)>(component: TComponentConstruct): TComponentConstruct; } /** - * Connects a React component to a Redux store. - * - * - Without arguments, just wraps the component, without changing the behavior / props - * - * - If 2 params are passed (3rd param, mergeProps, is skipped), default behavior - * is to override ownProps (as stated in the docs), so what remains is everything that's - * not a state or dispatch prop - * - * - When 3rd param is passed, we don't know if ownProps propagate and whether they - * should be valid component props, because it depends on mergeProps implementation. - * As such, it is the user's responsibility to extend ownProps interface from state or - * dispatch props or both when applicable - * - * @param mapStateToProps - * @param mapDispatchToProps - * @param mergeProps - * @param options - */ + * Connects a React component to a Redux store. + * + * - Without arguments, just wraps the component, without changing the behavior / props + * + * - If 2 params are passed (3rd param, mergeProps, is skipped), default behavior + * is to override ownProps (as stated in the docs), so what remains is everything that's + * not a state or dispatch prop + * + * - When 3rd param is passed, we don't know if ownProps propagate and whether they + * should be valid component props, because it depends on mergeProps implementation. + * As such, it is the user's responsibility to extend ownProps interface from state or + * dispatch props or both when applicable + * + * @param mapStateToProps + * @param mapDispatchToProps + * @param mergeProps + * @param options + */ export function connect(): InferableComponentDecorator; export function connect( mapStateToProps: FuncOrSelf>, - mapDispatchToProps?: FuncOrSelf|MapDispatchToPropsObject> - ): ComponentDecorator; + mapDispatchToProps?: FuncOrSelf | MapDispatchToPropsObject> + ): ComponentClassDecorator; export function connect( mapStateToProps: FuncOrSelf>, - mapDispatchToProps: FuncOrSelf|MapDispatchToPropsObject>, + mapDispatchToProps: FuncOrSelf | MapDispatchToPropsObject>, mergeProps: MergeProps, options?: Options - ): ComponentDecorator; + ): ComponentClassDecorator; + + export function connect( + mapStateToProps: FuncOrSelf>, + mapDispatchToProps?: FuncOrSelf | MapDispatchToPropsObject> + ): ComponentDecorator; + + export function connect( + mapStateToProps: FuncOrSelf>, + mapDispatchToProps: FuncOrSelf | MapDispatchToPropsObject>, + mergeProps: MergeProps, + options?: Options + ): ComponentDecorator; type FuncOrSelf = T | (() => T); @@ -88,7 +109,7 @@ declare namespace ReactRedux { */ pure?: boolean; /** - * If true, stores a ref to the wrapped component instance and makes it available via + * If true, stores a ref to the wrapped component instance and makes it available via * getWrappedInstance() method. Defaults to false. */ withRef?: boolean;