type Setter = { classSetter: ClassSetter functionSetter: FunctionSetter } type FunctionSetter = { [modelName: string]: { [actionName: string]: { setState: React.Dispatch selector?: Function selectorRef?: unknown } } } type Equals = (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? true : false interface Global { Actions: { [modelName: string]: { [actionName: string]: Action } } State: { [modelName: string]: any } mutableState: { [modelName: string]: any } AsyncState: { [modelName: string]: undefined | ((context?: any) => Promise>) } Context: any Middlewares: { [modelName: string]: Middleware[] } subscriptions: Subscriptions Setter: Setter devTools: any withDevTools: boolean gid: number uid: number storeId: number currentStoreId: string } type ClassSetter = React.Dispatch | undefined type Action = ( params: P, context: { state: S actions: getConsumerActionsType> } & ExtContext ) => | Partial | Promise | ProduceFunc | void> | ProduceFunc | void type ProduceFunc = (state: S) => void // v3.0 Actions type Actions = { [P in keyof ActionKeys]: Action } // v4.1+ Custom Hooks type CustomModelHook = () => State type Dispatch = (value: A) => void type SetStateAction = S | ((prevState: S) => S) interface ModelContext { modelName: string } interface BaseContext { action: Action consumerActions: ( actions: Actions, modelContext: ModelContext ) => getConsumerActionsType params: P middlewareConfig?: Object actionName: string modelName: string next?: Function disableSelectorUpdate?: boolean newState: Global['State'] | Function | null Global: Global } interface InnerContext extends BaseContext { // Actions with function type context will always invoke current component's reload. // f -> function, o -> outer, c -> class, u -> useModel type?: 'f' | 'o' | 'c' | 'u' __hash?: string } type Context = InnerContext & { next: Function modelMiddlewares?: Middleware[] } type Middleware = (C: Context, M: Middleware[]) => Promise type MiddlewareConfig = { logger: { enable: boolean | ((context: BaseContext) => boolean) } devtools: { enable: boolean } tryCatch: { enable: boolean } } interface Models { [name: string]: | ModelType | API> } type Selector = (state: S) => R interface API> { __id: string __ERROR__?: boolean useStore: < F extends Selector, any> = Selector< Get, unknown > >( selector?: F ) => [ F extends Selector, any> ? Equals, unknown>> extends true ? Get : ReturnType : Get, getConsumerActionsType> ] getState: () => Readonly> subscribe: ( actionName: keyof MT['actions'] | Array, callback: (context: BaseContext) => void ) => void unsubscribe: ( actionName: keyof Get | Array> ) => void actions: Readonly>> } interface LaneAPI { useStore: () => S getState: () => S getStore: () => S | undefined subscribe: (callback: () => void) => void unsubscribe: (callback: () => void) => void } interface APIs { useStore: < K extends keyof M, S extends M[K] extends API ? ArgumentTypes>[1] : M[K] extends ModelType ? Selector, unknown> : any >( name: K, selector?: S ) => M[K] extends API ? S extends (...args: any) => void ? Equals extends true ? [ReturnType>, Get] : ReturnType : ReturnType> : M[K] extends ModelType ? S extends (...args: any) => void ? [ Equals, unknown> extends true ? Get : ReturnType, getConsumerActionsType> ] : [Get, getConsumerActionsType>] : any getState: ( modelName: K ) => M[K] extends ModelType ? Readonly> : M[K] extends API ? ReturnType> : any getActions: ( modelName: K ) => M[K] extends ModelType ? Readonly>> : M[K] extends API ? M[K]['actions'] : unknown getInitialState: ( context?: T | undefined, config?: { isServer: boolean } ) => Promise<{ [modelName: string]: any }> subscribe: ( modelName: K, actionName: keyof Get | Array>, callback: (context: BaseContext) => void ) => void unsubscribe: ( modelName: K, actionName: keyof Get | Array> ) => void actions: { [K in keyof M]: M[K] extends API ? M[K]['actions'] : Readonly>> } } // v3.0 type ModelType< InitStateType = any, ActionKeys = any, ExtContext extends {} = {} > = { __ERROR__?: boolean actions: { [P in keyof ActionKeys]: Action< InitStateType, ActionKeys[P], ActionKeys, ExtContext > } middlewares?: Middleware[] state: InitStateType asyncState?: (context?: any) => Promise> } type ArgumentTypes = F extends (...args: infer A) => any ? A : never // v3.0 // TODO: ArgumentTypes[0] = undefined | string type getConsumerActionsType> = { [P in keyof A]: ArgumentTypes[0] extends undefined ? (params?: ArgumentTypes[0]) => ReturnType : (params: ArgumentTypes[0]) => ReturnType } type Get = Object[K] type ModelsProps = { useStore: ( name: K, models?: M ) => M[K] extends ModelType ? [Get, getConsumerActionsType>] : M[K] getState: ( modelName: K ) => M[K] extends ModelType ? Readonly> : M[K] } type Subscriptions = { [key: string]: Function[] }