В globalizeSelectors
тип sliceSelectors
равен {[key: string]: SliceSelector<TKey, T> }
.Но кто должен быть в этом случае?В вашей простой версии T
будет типом возврата этого конкретного селектора слайса, но при отображении нескольких T
не может быть всех типов возврата.
Решение, которое я бы использовал, состоит в том, чтобы использовать T
для повторного представления всего типа sliceSelectors
с тем ограничением, что все члены должны быть типа SliceSelector<TKey, any>
.any
там просто означает, что нам все равно, какой тип возврата у селекторов срезов.
Несмотря на то, что нам не важно, какой тип возврата у каждого селектора срезов, T
будет захватыватьактуальный тип (то есть типы возврата каждой функции в объекте будут не any
, а фактический тип).Затем мы можем использовать T
для создания сопоставленного типа, который глобализирует каждую функцию в объекте.
import { mapValues } from 'lodash'
// my (fake) redux state types
type SliceAState = { name: string }
type SliceBState = { isWhatever: boolean }
type GlobalState = {
a: SliceAState;
b: SliceBState;
}
type StateKey = keyof GlobalState
type GlobalizedSelector<TResult> = Selector<GlobalState, TResult>
const globalizeSelector = <TKey extends StateKey, Result>(
sliceKey: TKey,
sliceSelector: Selector<StateSlice<TKey>, Result>
): GlobalizedSelector<Result> => state => sliceSelector(state[sliceKey])
// an example of a map of selectors as they might be exported from their source file
const sliceASelectors = {
getName: (state: SliceAState): string => state.name,
getNameLength: (state: SliceAState): number => state.name.length
}
// fake global state
const globalState: GlobalState = {
a: { name: 'My Name' },
b: { isWhatever: true }
}
type Selector<TState, TResult> = (state: TState) => TResult
type StateSlice<TKey extends StateKey> = GlobalState[TKey]
// Simplified selctor, not sure what the conditional type here was trying to achive
type SliceSelector<TKey extends StateKey, TResult> = Selector<StateSlice<TKey>, TResult>
const globalizeSelectors = <TKey extends StateKey, T extends {
[P in keyof T]: SliceSelector<TKey, any>
}>(
sliceKey: TKey,
sliceSelectors: T
) : { [P in keyof T]: GlobalizedSelector<ReturnType<T[P]>> } => mapValues(sliceSelectors, s => globalizeSelector(sliceKey, s as any)) as any // Not sure about mapValues
const globalized = globalizeSelectors('a', sliceASelectors)
const globalizedGetName2: string = globalized.getName(globalState)
Единственная небольшая проблема заключается в том, что для работы mapValues
требуются утверждения некоторых типов, я не думаю, что mapValues
оборудован для работы с этими типами.