diff --git a/types/react-redux/index.d.ts b/types/react-redux/index.d.ts index 5adeb43612..624bc0b680 100644 --- a/types/react-redux/index.d.ts +++ b/types/react-redux/index.d.ts @@ -44,6 +44,8 @@ import { Store } from 'redux'; +import { NonReactStatics } from 'hoist-non-react-statics'; + // Omit taken from https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html export type Omit = Pick>; @@ -96,7 +98,10 @@ export type GetProps = C extends ComponentType ? P : never; // Applies LibraryManagedAttributes (proper handling of defaultProps // and propTypes), as well as defines WrappedComponent. -export type ConnectedComponentClass = ComponentClass> & { +export type ConnectedComponentClass< + C extends ComponentType, + P +> = ComponentClass> & NonReactStatics & { WrappedComponent: C; }; diff --git a/types/react-redux/react-redux-tests.tsx b/types/react-redux/react-redux-tests.tsx index ee5b9c1d94..085874a523 100644 --- a/types/react-redux/react-redux-tests.tsx +++ b/types/react-redux/react-redux-tests.tsx @@ -1167,6 +1167,48 @@ function TestLibraryManagedAttributes() { { }} />; } +function TestNonReactStatics() { + interface OwnProps { + bar: number; + } + + interface MapStateProps { + foo: string; + } + + class Component extends React.Component { + static defaultProps = { + bar: 0, + }; + + static meaningOfLife = 42; + + render() { + return
; + } + } + + function mapStateToProps(state: any): MapStateProps { + return { + foo: 'foo', + }; + } + + Component.meaningOfLife; + Component.defaultProps.bar; + + const ConnectedComponent = connect(mapStateToProps)(Component); + + // This is a non-React static and should be hoisted as-is. + ConnectedComponent.meaningOfLife; + + // This is a React static, so it's not hoisted. + // However, ConnectedComponent is still a ComponentClass, which specifies `defaultProps` + // as an optional static member. We can force an error (and assert that `defaultProps` + // wasn't hoisted) by reaching into the `defaultProps` object without a null check. + ConnectedComponent.defaultProps.bar; // $ExpectError +} + function TestProviderContext() { const store: Store = createStore((state = {}) => state); const nullContext = React.createContext(null);