如何在TypeScript中实现State到StateMutationSpec的递归映射类型?
解决方案
你需要的递归类型映射实现如下:
// 核心递归映射类型 type DeepMutationSpec<T> = // 每个层级支持两种选择:直接传新值,或者传入变更函数 T | StateMutator<T extends object ? DeepMutationSpecObject<T> : T>; // 遍历对象属性递归处理 type DeepMutationSpecObject<T extends object> = { [K in keyof T]: DeepMutationSpec<T[K]>; };
如果需要跳过Date、正则、函数这类特殊对象的递归展开,可以调整为兼容特殊类型的版本:
type DeepMutationSpec<T> = T | StateMutator< // 特殊类型直接返回原类型,不递归展开 T extends Date | RegExp | Function ? T : T extends object ? DeepMutationSpecObject<T> : T >; type DeepMutationSpecObject<T extends object> = { [K in keyof T]: DeepMutationSpec<T[K]>; };
配套工具函数类型调整
适配类型体系的工具函数定义如下,和你的使用示例完全兼容:
// 原有的变更函数定义保持不变 type StateMutator<TState> = (state: TState) => TState; // 调整append类型 function append<TArray extends any[]>(item: TArray[number]): StateMutator<TArray> { throw new Error("Not implemented") } // 调整patch类型 function patch<T>(spec: DeepMutationSpec<T>): StateMutator<T> { throw new Error("Not implemented"); } // 调整createNextState为泛型,支持任意结构的State function createNextState<T>(spec: DeepMutationSpec<T>, initialState: T): T { throw new Error("Not implemented") } type ItemOf<T> = T extends Array<infer TItem> ? TItem : never;
效果验证
代入你给出的State结构测试,生成的类型和你期望的StateMutationSpec完全一致:
interface State { a: { bs: number[], c: boolean} } // 用法和你的示例完全匹配,全程类型安全 const nextState: State = createNextState({ a: patch({ bs: append(1), c: false }) }, {} as State);
内容的提问来源于stack exchange,提问作者Gregor Woiwode
相关产品推荐
相关产品推荐

