// Type definitions for @rematch/select 2.0.0 // Definitions by: Sam Richard import { ExtractRematchStateFromModels, Models, Model, Action, RematchRootState, ModelReducers, ModelEffects, ModelEffectsCreator, } from '@rematch/core' import * as Reselect from 'reselect' import { Store as ReduxStore, Reducer as ReduxReducer } from 'redux' export { createSelector, createStructuredSelector } from 'reselect' export type Selector = TProps extends void ? (state: TState) => TReturns : (state: TState, props: TProps) => TReturns export type ExtractSelectorsFromModel< TModels extends Models, TModel extends Model > = // thunk case: (models) => ({...}) TModel['selectors'] extends (...args: any[]) => infer TReturnObj ? TReturnObj : // normal object case TModel['selectors'] extends Record ? TModel['selectors'] : never export type ExtractSelectorsSignatureFromSelectorsModel< TRootState, TSelectorsConfigObject, TKey extends keyof TSelectorsConfigObject > = TSelectorsConfigObject[TKey] extends (...args: any[]) => infer TSelector ? // hasProps case TSelector extends (props: infer TProps) => Selector ? (props: TProps) => Selector : // selector without props case TSelector extends Selector ? Selector : // selector with props case TSelector extends Selector ? Selector : never : never export interface SelectConfig< TModels extends Models, TExtraModels extends Models > { sliceState?: ( state: ExtractRematchStateFromModels, model: Model ) => Record | undefined selectorCreator?: any } export type ModelSelectors< TModels extends Models, TExtraModels extends Models, TModel extends Model > = { [key in keyof ExtractSelectorsFromModel< TModels, TModel >]: ExtractSelectorsSignatureFromSelectorsModel< RematchRootState, ExtractSelectorsFromModel, key > } export type Slicer = (( resultFn: (slice: TSliceState) => TReturns ) => Selector) & Selector export interface ModelSelectorFactories< TModels extends Models, TExtraModels extends Models, TSliceState = any > { [key: string]: | SelectorFactory | SelectorParametricFactory } export type StoreSelectors< TModels extends Models, TExtraModels extends Models > = { [TModelKey in keyof TModels]: ModelSelectors< TModels, TExtraModels, TModels[TModelKey] > } export type SelectorFactory< TModels extends Models, TExtraModels extends Models, TSliceState = any > = ( // FIXME: https://github.com/Microsoft/TypeScript/issues/27862 this: ModelSelectorFactories, models: StoreSelectors ) => Selector, TReturns> export type SelectorParametricFactory< TModels extends Models, TExtraModels extends Models, TSliceState = any, TProps = any, TReturns = any > = ( // FIXME: https://github.com/Microsoft/TypeScript/issues/27862 this: ModelSelectorFactories, models: StoreSelectors, props: TProps ) => Selector, TReturns, TProps> // the same as `SelectorParametricFactory` but with different return signature export type ParameterizerSelectorFactory< TModels extends Models, TExtraModels extends Models, TSliceState = any, TProps = any, TReturns = any > = ( // FIXME: https://github.com/Microsoft/TypeScript/issues/27862 this: ModelSelectorFactories, models: StoreSelectors, props: TProps ) => (props: TProps) => Selector, TReturns> export type Parameterizer< TModels extends Models, TExtraModels extends Models, TSliceState = any > = ( factory: SelectorParametricFactory< TModels, TExtraModels, TSliceState, TProps, TReturns > ) => ParameterizerSelectorFactory< TModels, TExtraModels, TSliceState, TProps, TReturns > export type ModelSelectorsFactory< TModels extends Models, TExtraModels extends Models, TSliceState = any > = ( slice: Slicer>, createSelector: typeof Reselect.createSelector, hasProps: Parameterizer ) => ModelSelectorFactories export type ModelSelectorsConfig< TModels extends Models, TSliceState = any, TExtraModels extends Models = Record > = | ModelSelectorsFactory | ModelSelectorFactories export type RematchSelect< TModels extends Models, TExtraModels extends Models, TRootState = RematchRootState > = ( any }>( mapSelectToProps: (select: RematchSelect) => TReturn ) => Reselect.OutputParametricSelector< TRootState, any, { [K in keyof TReturn]: ReturnType }, Reselect.Selector > & Reselect.OutputSelector< TRootState, { [K in keyof TReturn]: ReturnType }, Reselect.Selector >) & StoreSelectors declare module '@rematch/core' { // Add overloads for store to add select interface RematchStore< TModels extends Models, TExtraModels extends Models > extends ReduxStore, Action> { select: RematchSelect< TModels, TExtraModels, RematchRootState > } // add overloads for Model here. interface Model, TState = any> { selectors?: ModelSelectorsConfig } // add overloads for ModelCreator here. interface ModelCreator { >(): < R extends ModelReducers | undefined, BR extends ReduxReducer | undefined, E extends ModelEffects | ModelEffectsCreator | undefined, SE extends ModelSelectorsConfig | undefined, S, BS = S >(mo: { name?: string state: S reducers?: R baseReducer?: BR effects?: E selectors?: SE }) => { name?: string state: S } & (E extends undefined ? {} : { effects: E }) & (R extends undefined ? {} : { reducers: R }) & (BR extends undefined ? {} : { baseReducer: BR }) & (SE extends undefined ? {} : { selectors: SE }) } }