redux 个人记录

85 阅读2分钟

官方文档


import type React from 'react'; 

type reducerName = string;
type sliceName = string;
type reducerType = `${sliceName}/${reducerName}`;
interface createSlice {
    ( options: createSliceOptions ): slice;
}

interface createSliceOptions {
    name: sliceName;
    initialState: Record<string ,any>;
    reducers: {
        [key: reducerName]: (state: any, action: any) => void;
    }
}

interface slice {
    name: createSliceOptions['name'];
    reducer: ReturnType<builderReducerCreator>['reducer'];
    actions: {
        [key: keyof createSliceOptions['reducers']]: actionCreators;
    };
    getInitialState: ReturnType<buildReducer>['getInitialState'];   // () => createSliceOptions['initialState'];
    [key: string]: any;
}

namespace createReducer { 
    export interface reducer {
        (state: createSliceOptions['initialState'], action: any): createSliceOptions['initialState'];
        getInitialState: () => createSliceOptions['initialState'];
    }  
}

interface buildReducer {
    (initialState: createSliceOptions['initialState'], builder: buildReducer['builderCallback']): createReducer.reducer;
    builderCallback: (builder: builder)=> [buildReducer['actionMap'], any, any];
    actionMap : {
        [key: reducerType]: createSliceOptions['reducers'][keyof createSliceOptions['reducers']];
    }
}


interface builder {
    addCase(typeOrActionCreator: any, reducer: any): this;
    addMatcher(matcher: any, reducer: any): this;
    addDefaultCase(reducer: any): this; 
}

interface builderReducerCreator {
    (): {
        reducer: (state: createSliceOptions['initialState'], action: ReturnType<actionCreators>) => ReturnType<createReducer.reducer>;
        preparedReducer: (prepare: any, reducer: any) => void;
        asyncThunk: (payloadCreator: any, config: any) => void;
    }
}

interface actionCreators {
    (...args: any): {
        type: string;
        payload: typeof args[0];   
    };
    toString: () => `${createSliceOptions['name']}/${keyof createSliceOptions['reducers']}`;
    type: ReturnType<actionCreators['toString']>;
    match: (action: any) => boolean;
}

interface configureStore {
    ( options: configureStoreOptions ): configureStore.returnResult;
}

interface configureStoreOptions {
    reducer: {
        [key: string]: slice['reducer'];
    }
}

namespace configureStore {
    export namespace buildGetDefaultMiddleware {
        export type buildGetDefaultMiddleware = () => getDefaultMiddleware;
        export type getDefaultMiddleware = (options?: any) => thunk.middleware[];
    }; 

    export type finalMiddleware = ReturnType<buildGetDefaultMiddleware.getDefaultMiddleware>;

    type middlewareEnhancer = ReturnType<redux.applyMiddleware>;

    export type buildGetDefaultEnhancers = (middlewareEnhancer: middlewareEnhancer) => getDefaultEnhancers;

    export type getDefaultEnhancers = (options?: any)=> [ReturnType<redux.applyMiddleware>, autoBatchEnhancer.autoBatchEnhancer];

    export type composedEnhancer = redux.compose<ReturnType<getDefaultEnhancers>>;

    export type returnResult = ReturnType<redux.createStore.createStore>;
}



namespace thunk {
    export type middleware = ({dispatch, getState}) => (next: any) => (action: any) => any;
}

namespace redux {
    type Func<T extends any[], R> = (...a: T) => R
    /* 
        更改dispatch方法,对store.dispatch进行增强, 
    */
    export type applyMiddleware = (...middleware: configureStore.finalMiddleware[]) => (createStore: createStore.createStore) => (reducer: combineReducers.combineReducers['combination'], preloadedState: any)=> {};

    export namespace createStore {

        export interface createStore {
            //  enhancer: (createStore)(reducer, preloadedState);
            <T = combineReducers.combineReducers['combination'], E = configureStore.composedEnhancer>(reducer: T, preloadedState: any, enhancer:E ): store;
        }

 

        export interface store<A = any, T = any> {
            // todo middleware  and thunk
            dispatch: <T extends ReturnType<actionCreators>>(action: T) => T;
            /* 
                call {
                    Parameters<createStore.createStore>[0]()
                }
            */
            getState: <A>() => A;
            subscribe: (listener: ()=>void ) => ()=>void;
        } 
    }

    export type store = createStore.store;
    export interface compose<R> {
        <R>(a: R): R;
        <F extends Function>(f: F): F;
        // (a,b)=>a(b(...arg))
        <A, T extends any[], R>(
            f1: (a: A) => R,
            f2: Func<T, A>
        ): Func<T, R>;
        
    }

    export interface compose<R> {
        (...funcs: Function[]): (...args: any[]) => R
    }

    export namespace combineReducers {
        export interface combineReducers {
            (reducers: {[key: string] : slice['reducer']}): combineReducers.combineReducers['combination'];
            combination: (state: any, action: ReturnType<actionCreators>) => any;
        }
    }
}

namespace autoBatchEnhancer {
    export type autoBatchEnhancer = (next) => (...args: any[]) => redux.createStore.store | {subscribe: (listener: ()=>void ) => ()=>void, dispatch: ReturnType<redux.createStore.store['dispatch']>};

} 



namespace Provider {
    export interface createSubscription {
        (store: configureStore.returnResult): subscription;
        listeners : {
            clear: ()=>void;
            notify: ()=>void;
            get: ()=>void;
            subscribe: (listener: ()=>void ) => ()=>void;
        }
    }

    export type subscription = {
        trySubscribe: ()=>void;
    }

    // export interface createSelectorHook{
    //     (context: React.context): {useSelector: createSelectorHook['useSelector']} | {withTypes : ()=>createSelectorHook['useSelector'] };
    //     useSelector: (select:()=>any, equalityFnOrOptions: {}) => any;
    // }

    export interface useSelector {
        <T>(select:()=>T, equalityFnOrOptions: {}): T;
    }

    export interface useDispatch {
        (): redux.createStore.store['dispatch'];
    }
}

interface connect {
    (mapStateToProps: any, mapDispatchToProps: any , mergeProps: any , option: any): connect['wrapWithConnect'];

    wrapWithConnect: (WrappedComponent: React.component)=> ReturnType<hoistNonReactStatics>;

    selectorFactoryOptions: {
        shouldHandleStateChanges: true;
        displayName: `ConnectComponent`;
        wrappedComponentName: 'Component';
        WrappedComponent: Parameters<connect['wrapWithConnect']>[0];
        initMapStateToProps: initProxySelector<Parameters<connect>[0], 'mapStateToProps'>;
        initMapDispatchToProps: initProxySelector<Parameters<connect>[1], 'mapDispatchToProps'>;
        initMergeProps: () => defaultMergeProps;
        areStatesEqual: () => boolean;
        areOwnPropsEqual: () => boolean;
        areStatePropsEqual: () => boolean;
        areMergedPropsEqual: () => boolean;
    }
}

interface ConnectFunction {
    (props: {}): React.component;
    propsContext: undefined;
    ContextToUse: React.Context;
    store: redux.store;
    defaultSelectorFactory: {
        (dispatch: redux.store['dispatch'], selectorFactoryOptions: connect['selectorFactoryOptions']): pureFinalPropsSelectorFactory;
        mapStateToProps: ReturnType<connect['selectorFactoryOptions']['initMapStateToProps']>;
        mapDispatchToProps: ReturnType<connect['selectorFactoryOptions']['initMapDispatchToProps']>;
        mergeProps: ReturnType<connect['selectorFactoryOptions']['initMergeProps']>;
    };
    subscription: createSubscription.subscription;
    notifyNestedSubs: createSubscription.subscription['notifyNestedSubs'];
    overriddenContextValue: redux.store | { subscription: createSubscription.subscription };
    actualChildPropsSelector: () => ReturnType<ConnectFunction['defaultSelectorFactory']>;
    subscribeForReact: (reactListener:()=>any)=>any;
}

interface initProxySelector<T, U> {
    (dispatch: redux.store['dispatch'], option: {displayName: string}): proxy;

}


interface pureFinalPropsSelectorFactory {
    // mapStateToProps , mapDispatchToProps , mergeProps , dispatch , Omit<selectorFactoryOptions, 'initMapStateToProps' | 'initMapDispatchToProps' | 'initMergeProps' >
    (nextState: redux.store['getState'], nextOwnProps): pureFinalPropsSelectorFactory['handleFirstCall'];

    handleFirstCall: (firstState, firstOwnProps)=>defaultMergeProps;
}

interface proxy {
    (stateOrDispatch,ownProps): ReturnType<proxy['mapToProps']>;
    dependsOnOwnProps: boolean;
    mapToProps: ()=>any;
}

interface defaultMergeProps<T =any, U = any , K = any> {
    (stateProps: T, dispatchProps: U, ownProps: K): T | U | K;
}

interface hoistNonReactStatics {
    // sourceComponent === WrappedComponent
    (targetComponent: ConnectFunction, sourceComponent: React.component): ConnectFunction;
}


namespace createSubscription {
    export type subscription = {
        addNestedSub: () => void;
        notifyNestedSubs: () => void;
        handleChangeWrapper: () => void;
        isSubscribed: () => boolean;
        trySubscribeSelf: () => void;
        tryUnsubscribeSelf: () => void;
        getListeners: () => void;
    }
}


/*
 useSelector :{
    const selectedState = useSyncExternalStore(
        subscription.addNestedSub,
        select(store.getState),
    )
    {
        addNestedSub{
            创建一个listener链表
            
        }
    }
    return selectedState
 }

 */