// Type definitions for react-redux 7.1 // Project: https://github.com/reduxjs/react-redux // Definitions by: Qubo , // Kenzie Togami , // Curits Layne // Frank Tan // Nicholas Boll // Dibyo Majumdar // Thomas Charlat // Valentin Descamps // Johann Rakotoharisoa // Anatoli Papirovski // Boris Sergeyev // Søren Bruus Frank // Jonathan Ziller // Dylan Vann // Yuki Ito // Kazuma Ebina // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 3.0 import { Component, ComponentType, StatelessComponent, Context, NamedExoticComponent } from 'react'; import { Action, ActionCreator, AnyAction, Dispatch, Store } from 'redux'; import hoistNonReactStatics = require('hoist-non-react-statics'); /** * This interface can be augmented by users to add default types for the root state when * using `react-redux`. * Use module augmentation to append your own type definition in a your_custom_type.d.ts file. * https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation */ // tslint:disable-next-line:no-empty-interface export interface DefaultRootState {} export type AnyIfEmpty = keyof T extends never ? any : T; export type RootStateOrAny = AnyIfEmpty; // Omit taken from https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html export type Omit = Pick>; export interface DispatchProp { dispatch: Dispatch; } export type AdvancedComponentDecorator = (component: ComponentType) => NamedExoticComponent; /** * A property P will be present if: * - it is present in DecorationTargetProps * * Its value will be dependent on the following conditions * - if property P is present in InjectedProps and its definition extends the definition * in DecorationTargetProps, then its definition will be that of DecorationTargetProps[P] * - if property P is not present in InjectedProps then its definition will be that of * DecorationTargetProps[P] * - if property P is present in InjectedProps but does not extend the * DecorationTargetProps[P] definition, its definition will be that of InjectedProps[P] */ export type Matching = { [P in keyof DecorationTargetProps]: P extends keyof InjectedProps ? InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : InjectedProps[P] : DecorationTargetProps[P]; }; /** * a property P will be present if : * - it is present in both DecorationTargetProps and InjectedProps * - InjectedProps[P] can satisfy DecorationTargetProps[P] * ie: decorated component can accept more types than decorator is injecting * * For decoration, inject props or ownProps are all optionally * required by the decorated (right hand side) component. * But any property required by the decorated component must be satisfied by the injected property. */ export type Shared< InjectedProps, DecorationTargetProps > = { [P in Extract]?: InjectedProps[P] extends DecorationTargetProps[P] ? DecorationTargetProps[P] : never; }; // Infers prop type from component C export type GetProps = C extends ComponentType ? P : never; // Applies LibraryManagedAttributes (proper handling of defaultProps // and propTypes), as well as defines WrappedComponent. export type ConnectedComponent< C extends ComponentType, P > = NamedExoticComponent> & hoistNonReactStatics.NonReactStatics & { WrappedComponent: C; }; // Injects props and removes them from the prop requirements. // Will not pass through the injected props if they are passed in during // render. Also adds new prop requirements from TNeedsProps. export type InferableComponentEnhancerWithProps = >>>( component: C ) => ConnectedComponent, keyof Shared>> & TNeedsProps>; // Injects props and removes them from the prop requirements. // Will not pass through the injected props if they are passed in during // render. export type InferableComponentEnhancer = InferableComponentEnhancerWithProps; export type InferThunkActionCreatorType any> = TActionCreator extends (...args: infer TParams) => (...args: any[]) => infer TReturn ? (...args: TParams) => TReturn : TActionCreator; export type HandleThunkActionCreator = TActionCreator extends (...args: any[]) => any ? InferThunkActionCreatorType : TActionCreator; // redux-thunk middleware returns thunk's return value from dispatch call // https://github.com/reduxjs/redux-thunk#composition export type ResolveThunks = TDispatchProps extends { [key: string]: any } ? { [C in keyof TDispatchProps]: HandleThunkActionCreator } : TDispatchProps; // the conditional type is to support TypeScript 3.0, which does not support mapping over tuples and arrays; // once the typings are updated to at least TypeScript 3.1, a simple mapped type can replace this mess export type ResolveArrayThunks> = TDispatchProps extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, infer A8, infer A9] ? [HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7, infer A8] ? [HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6, infer A7] ? [HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1, infer A2, infer A3, infer A4, infer A5, infer A6] ? [HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1, infer A2, infer A3, infer A4, infer A5] ? [HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1, infer A2, infer A3, infer A4] ? [HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1, infer A2, infer A3] ? [HandleThunkActionCreator, HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1, infer A2] ? [HandleThunkActionCreator, HandleThunkActionCreator] : TDispatchProps extends [infer A1] ? [HandleThunkActionCreator] : TDispatchProps extends Array ? Array> : TDispatchProps extends ReadonlyArray ? ReadonlyArray> : never ; /** * 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 interface Connect { // tslint:disable:no-unnecessary-generics (): InferableComponentEnhancer; ( mapStateToProps: MapStateToPropsParam ): InferableComponentEnhancerWithProps; ( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsNonObject ): InferableComponentEnhancerWithProps; ( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsParam, ): InferableComponentEnhancerWithProps< ResolveThunks, TOwnProps >; ( mapStateToProps: MapStateToPropsParam, mapDispatchToProps: MapDispatchToPropsNonObject ): InferableComponentEnhancerWithProps; ( mapStateToProps: MapStateToPropsParam, mapDispatchToProps: MapDispatchToPropsParam, ): InferableComponentEnhancerWithProps< TStateProps & ResolveThunks, TOwnProps >; ( mapStateToProps: null | undefined, mapDispatchToProps: null | undefined, mergeProps: MergeProps, ): InferableComponentEnhancerWithProps; ( mapStateToProps: MapStateToPropsParam, mapDispatchToProps: null | undefined, mergeProps: MergeProps, ): InferableComponentEnhancerWithProps; ( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsParam, mergeProps: MergeProps, ): InferableComponentEnhancerWithProps; ( mapStateToProps: MapStateToPropsParam, mapDispatchToProps: null | undefined, mergeProps: null | undefined, options: Options ): InferableComponentEnhancerWithProps; ( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsNonObject, mergeProps: null | undefined, options: Options<{}, TStateProps, TOwnProps> ): InferableComponentEnhancerWithProps; ( mapStateToProps: null | undefined, mapDispatchToProps: MapDispatchToPropsParam, mergeProps: null | undefined, options: Options<{}, TStateProps, TOwnProps> ): InferableComponentEnhancerWithProps< ResolveThunks, TOwnProps >; ( mapStateToProps: MapStateToPropsParam, mapDispatchToProps: MapDispatchToPropsNonObject, mergeProps: null | undefined, options: Options ): InferableComponentEnhancerWithProps; ( mapStateToProps: MapStateToPropsParam, mapDispatchToProps: MapDispatchToPropsParam, mergeProps: null | undefined, options: Options ): InferableComponentEnhancerWithProps< TStateProps & ResolveThunks, TOwnProps >; ( mapStateToProps: MapStateToPropsParam, mapDispatchToProps: MapDispatchToPropsParam, mergeProps: MergeProps, options?: Options ): InferableComponentEnhancerWithProps; // tslint:enable:no-unnecessary-generics } /** * Infers the type of props that a connector will inject into a component. */ export type ConnectedProps = TConnector extends InferableComponentEnhancerWithProps ? TInjectedProps : never; /** * The connect function. See {@type Connect} for details. */ export const connect: Connect; export type MapStateToProps = (state: State, ownProps: TOwnProps) => TStateProps; export type MapStateToPropsFactory = (initialState: State, ownProps: TOwnProps) => MapStateToProps; export type MapStateToPropsParam = MapStateToPropsFactory | MapStateToProps | null | undefined; export type MapDispatchToPropsFunction = (dispatch: Dispatch, ownProps: TOwnProps) => TDispatchProps; export type MapDispatchToProps = MapDispatchToPropsFunction | TDispatchProps; export type MapDispatchToPropsFactory = (dispatch: Dispatch, ownProps: TOwnProps) => MapDispatchToPropsFunction; export type MapDispatchToPropsParam = MapDispatchToPropsFactory | MapDispatchToProps; export type MapDispatchToPropsNonObject = MapDispatchToPropsFactory | MapDispatchToPropsFunction; export type MergeProps = (stateProps: TStateProps, dispatchProps: TDispatchProps, ownProps: TOwnProps) => TMergedProps; export interface Options extends ConnectOptions { /** * If true, implements shouldComponentUpdate and shallowly compares the result of mergeProps, * preventing unnecessary updates, assuming that the component is a “pure” component * and does not rely on any input or state other than its props and the selected Redux store’s state. * Defaults to true. * @default true */ pure?: boolean; /** * When pure, compares incoming store state to its previous value. * @default strictEqual */ areStatesEqual?: (nextState: State, prevState: State) => boolean; /** * When pure, compares incoming props to its previous value. * @default shallowEqual */ areOwnPropsEqual?: (nextOwnProps: TOwnProps, prevOwnProps: TOwnProps) => boolean; /** * When pure, compares the result of mapStateToProps to its previous value. * @default shallowEqual */ areStatePropsEqual?: (nextStateProps: TStateProps, prevStateProps: TStateProps) => boolean; /** * When pure, compares the result of mergeProps to its previous value. * @default shallowEqual */ areMergedPropsEqual?: (nextMergedProps: TMergedProps, prevMergedProps: TMergedProps) => boolean; /** * If true, use React's forwardRef to expose a ref of the wrapped component * * @default false */ forwardRef?: boolean; } /** * Connects a React component to a Redux store. It is the base for {@link connect} but is less opinionated about * how to combine state, props, and dispatch into your final props. It makes no * assumptions about defaults or memoization of results, leaving those responsibilities to the caller.It does not * modify the component class passed to it; instead, it returns a new, connected component for you to use. * * @param selectorFactory The selector factory. See SelectorFactory type for details. * @param connectOptions If specified, further customizes the behavior of the connector. Additionally, any extra * options will be passed through to your selectorFactory in the factoryOptions argument. */ export function connectAdvanced( // tslint:disable-next-line no-unnecessary-generics selectorFactory: SelectorFactory, connectOptions?: ConnectOptions & TFactoryOptions ): AdvancedComponentDecorator; /** * Initializes a selector function (during each instance's constructor). That selector function is called any time the * connector component needs to compute new props, as a result of a store state change or receiving new props. The * result of selector is expected to be a plain object, which is passed as the props to the wrapped * component. If a consecutive call to selector returns the same object (===) as its previous * call, the component will not be re-rendered. It's the responsibility of selector to return that * previous object when appropriate. */ export type SelectorFactory = (dispatch: Dispatch, factoryOptions: TFactoryOptions) => Selector; export type Selector = TOwnProps extends null | undefined ? (state: S) => TProps : (state: S, ownProps: TOwnProps) => TProps; export interface ConnectOptions { /** * Computes the connector component's displayName property relative to that of the wrapped component. Usually * overridden by wrapper functions. * * @default name => 'ConnectAdvanced('+name+')' * @param componentName */ getDisplayName?: (componentName: string) => string; /** * Shown in error messages. Usually overridden by wrapper functions. * * @default 'connectAdvanced' */ methodName?: string; /** * If defined, a property named this value will be added to the props passed to the wrapped component. Its value * will be the number of times the component has been rendered, which can be useful for tracking down unnecessary * re-renders. * * @default undefined */ renderCountProp?: string; /** * Controls whether the connector component subscribes to redux store state changes. If set to false, it will only * re-render on componentWillReceiveProps. * * @default true */ shouldHandleStateChanges?: boolean; /** * The key of props/context to get the store. You probably only need this if you are in the inadvisable position of * having multiple stores. * * @default 'store' */ storeKey?: string; /** * @deprecated Use forwardRef * * @default false */ withRef?: boolean; /** * The react context to get the store from. * * @default ReactReduxContext */ context?: Context; } export interface ReactReduxContextValue { store: Store; storeState: SS; } export interface ProviderProps { /** * The single Redux store in your application. */ store: Store; /** * Optional context to be used internally in react-redux. Use React.createContext() to create a context to be used. * If this is used, generate own connect HOC by using connectAdvanced, supplying the same context provided to the * Provider. Initial value doesn't matter, as it is overwritten with the internal state of Provider. */ context?: Context; } /** * Makes the Redux store available to the connect() calls in the component hierarchy below. */ export class Provider extends Component> { } /** * Exposes the internal context used in react-redux. It is generally advised to use the connect HOC to connect to the * redux store instead of this approeach. */ export const ReactReduxContext: Context; /** * Wraps ReactDOM or React Native's internal unstable_batchedUpdate function. You can use it to ensure that * multiple actions dispatched outside of React only result in a single render update. */ export function batch(cb: () => void): void; // tslint:disable:no-unnecessary-generics /** * Compares two arbitrary values for shallow equality. Object values are compared based on their keys, i.e. they must * have the same keys and for each key the value must be equal according to the `Object.is()` algorithm. Non-object * values are also compared with the same algorithm as `Object.is()`. */ export function shallowEqual(left: T, right: any): boolean; /** * A hook to access the redux `dispatch` function. * * Note for `redux-thunk` users: the return type of the returned `dispatch` functions for thunks is incorrect. * However, it is possible to get a correctly typed `dispatch` function by creating your own custom hook typed * from the store's dispatch function like this: `const useThunkDispatch = () => useDispatch();` * * @returns redux store's `dispatch` function * * @example * * import React from 'react' * import { useDispatch } from 'react-redux' * * export const CounterComponent = ({ value }) => { * const dispatch = useDispatch() * return ( *
* {value} * *
* ) * } */ // NOTE: the first overload below and note above can be removed if redux-thunk typings add an overload for // the Dispatch function (see also this PR: https://github.com/reduxjs/redux-thunk/pull/247) export function useDispatch>(): TDispatch; export function useDispatch
(): Dispatch; /** * A hook to access the redux store's state. This hook takes a selector function * as an argument. The selector is called with the store state. * * This hook takes an optional equality comparison function as the second parameter * that allows you to customize the way the selected state is compared to determine * whether the component needs to be re-rendered. * * If you do not want to have to specify the root state type for whenever you use * this hook with an inline selector you can use the `TypedUseSelectorHook` interface * to create a version of this hook that is properly typed for your root state. * * @param selector the selector function * @param equalityFn the function that will be used to determine equality * * @returns the selected state * * @example * * import React from 'react' * import { useSelector } from 'react-redux' * import { RootState } from './store' * * export const CounterComponent = () => { * const counter = useSelector((state: RootState) => state.counter) * return
{counter}
* } */ export function useSelector( selector: (state: TState) => TSelected, equalityFn?: (left: TSelected, right: TSelected) => boolean ): TSelected; /** * This interface allows you to easily create a hook that is properly typed for your * store's root state. * * @example * * interface RootState { * property: string; * } * * const useTypedSelector: TypedUseSelectorHook = useSelector; * */ export interface TypedUseSelectorHook { ( selector: (state: TState) => TSelected, equalityFn?: (left: TSelected, right: TSelected) => boolean ): TSelected; } /** * A hook to access the redux store. * * @returns the redux store * * @example * * import React from 'react' * import { useStore } from 'react-redux' * * export const ExampleComponent = () => { * const store = useStore() * return
{store.getState()}
* } */ export function useStore(): Store; /** * Hook factory, which creates a `useSelector` hook bound to a given context. * * @param Context passed to your ``. * @returns A `useSelector` hook bound to the specified context. */ export function createSelectorHook(context?: Context): typeof useSelector; /** * Hook factory, which creates a `useStore` hook bound to a given context. * * @param Context passed to your ``. * @returns A `useStore` hook bound to the specified context. */ export function createStoreHook(context?: Context): typeof useStore; /** * Hook factory, which creates a `useDispatch` hook bound to a given context. * * @param Context passed to your ``. * @returns A `useDispatch` hook bound to the specified context. */ export function createDispatchHook(context?: Context): typeof useDispatch; // tslint:enable:no-unnecessary-generics