我正在为redux-starter-kit创建一个包装器,以使其看起来更像Vuex。 Github仓库是here,我正在研究这个branch。这个项目是一个实验。问题是我无法正确检查这些减速器的类型。
如果您有类似函数的对象。
const reducers = {
addCounter(state:IState, payload:IActionPayload<number>):void {
state.counter += payload.payload;
}
}
它通过另一个函数并带走了第一个参数。您如何保持有效载荷的类型检查?
我可以在单个函数上使用泛型来执行此操作,并类型化返回
我不确定如何为对象中的每个函数动态地执行此操作。
答案 0 :(得分:0)
整天黑客入侵后。我从TypeScript类型中学到了很多东西,哇,它功能强大又难看。我对此还是很陌生,因此,如果有人有更好的选择,或者如果我误解了某些东西,请纠正我。
IActionPayload<number>
的类型// Formats a Reducer Function to remove state and place the
// payload parameter as the first parameter
type ReducerToAction <R> = R extends (...args: infer A) => any ? (payload:A[1]) => any : never
它可以工作,但肯定很难看。
全部与conditionals有关。如果它是一个函数,则将unknown[]
类型的args捕获为A,但是由于它是一个数组,我们可以说A[1]
并获取有效载荷。因此,如果它是一个函数返回类型(payload:A[1]) => any
否则为never
您可以用它来遍历对象。
type loop<obj> = { [key in keyof obj]: obj[key] }
现在我们需要对obj[key]
进行步骤1
type loop<obj> = { [key in keyof obj]: ReducerToAction<obj[key]> }
所以看起来像这样。
type ReducersToActions<R> = { [K in keyof R]: ReducerToAction<R[K]> }
IActionPayload<number>
类型如果您提供type
这样的处理方式。
type IActionPayload <T> = { type: string, payload: T }
似乎您可以访问密钥。因此,如果我们也将其置于条件中,则可以从对象中拉出单个键。
type PullPayloadType<P> = P extends IActionPayload<any> ? P['payload'] : never
应该用英语说出它是否为IActionPayload
类型,我们知道它具有密钥payload
,因此拉动它会返回never
。
有了这个,我们将需要更新其他类型以使用它,这将为您提供以下内容。
// Action Structure
type IActionPayload <T> = { type: string, payload: T }
// Reducers object structure
type IReduces = { [key:string] : (state:any, payload:IActionPayload<any>) => any }
// Gets the Payload type from an object that is of type IActionPayload
type PullPayloadType<P> = P extends IActionPayload<any> ? P['payload'] : never
// Formats a Reducer Function to remove state and place the payload parameter as the first parameter
type ReducerToAction<R> = R extends (...args: infer A) => any ? (payload:PullPayloadType<A[1]>) => any : never
// Formats Reducer Functions in a object that matches the type IReduces
type ReducersToActions<R extends IReduces> = { [K in keyof R]: ReducerToAction<R[K]> }