Нужно ожидать в машинописных дженериках - PullRequest
0 голосов
/ 04 февраля 2020

Я хотел бы напечатать функцию, которая создает редуктор. Я действительно близко, но это не работает.

// Single handler
type HandlerType<T, P> = (state: T, action: { action: string, payload?: any }) => Partial<T>

// Handlers object - key is string and value is a function as above
type HandlersType<T, P> = {
    [key in keyof P]: HandlerType<T, P>
}

const createReducer = <T, P>(
    initialState: T,
    handlers: HandlersType<T, P>,
) => (
    state = initialState,
    action: {
        [a in keyof P]: HandlerType<T, P>
    }
) => {
        const handler = handlers[action.type]

        if (handler) {
            return {
                ...state,
                ...handler(state, action),
            }
        }
    return state
}


// helper generic:
type StatePartial<T, P> = (state: T, { action, payload }: { action: string, payload: P }) => Partial<T>



// ==============================================
// usage:
//

// initial state type
export type StateType = {
    c: string,
    d: string
}

// actions type
export type Actions<T> = {
    'hello': StatePartial<T, string>
}

// actuall creator 
const a = createReducer<StateType, Actions<StateType>>(
    {
        c: 'meh',
        d: 'meh2'
    },
    {
        'hello': (state, payload) => {
            return {
                dateRange: payload
            }
        }
    },
)

Я хотел бы помочь, если это возможно, пожалуйста.

игровая площадка

1 Ответ

0 голосов
/ 04 февраля 2020

Понял! Я слишком точно указывал c с наборами текста. Если я использую дженерики, то можно набрать any

const createReducer = <T, P extends { [type: string]: any }>(
    initialState: T,
    handlers: P,
) => (
    state = initialState,  
    action: any //  <---- will still be recognized on the next layer
) => {
        const handler = handlers[action.type]

        if (handler) {
            return {
                ...state,
                ...handler(state, action),
            }
        }
        return state
    }


export type State = {
    c: string,
    d: string
}

export type Actions<T> = {
    'hello': (state: T, action: { action: string, payload: string }) => Partial<T>
}

const handlers: Actions<State> = {
    'hello': (state: State, { payload }) => {
        return {
            c: payload
        }
    }
}


const a = createReducer<State, Actions<State>>(
    {
        c: 'meh',
        d: 'meh2'
    },
    handlers,
)

ts детская площадка

...