能否基于条件为TypeScript映射类型动态应用修饰符?
动态为TypeScript映射类型字段应用修饰符的实现方案
问题描述
希望根据条件为TypeScript映射类型中的字段动态应用修饰符(例如将指定字段设为必填),尝试的代码无法合法运行:
type TestKey<T, K extends keyof T> = K extends 'b' ? true : false type RequiredIf<T> = { [K in keyof T]: TestKey<T, K> extends true ? T[K]-? : T[K] // ^无修饰符 ^^此处应用修饰符 } type test = RequiredIf<{a: 1, b?: 2, c?: 3}> // 期望得到 {a: 1, b: 2, c?: 3}
可行实现方案
TypeScript不支持在条件类型分支中直接使用-?这类修饰符操作,但可以通过内置工具类型组合或映射类型交叉来实现需求,以下是两种常用方案:
方案一:Pick + Required + Omit 组合
通过提取需要设为必填的字段,用Required处理后再与原类型的剩余字段合并:
type TestKey<T, K extends keyof T> = K extends 'b' ? true : false; // 筛选出需要设为必填的键 type RequiredKeys<T> = { [K in keyof T]: TestKey<T, K> extends true ? K : never }[keyof T]; type RequiredIf<T> = Omit<T, RequiredKeys<T>> & Required<Pick<T, RequiredKeys<T>>>; type test = RequiredIf<{a: 1, b?: 2, c?: 3}>; // 结果:{a: 1, b: 2, c?: 3}
方案二:映射类型交叉覆盖
利用交叉类型中必填属性覆盖可选属性的特性,单独处理需要设为必填的字段:
type TestKey<T, K extends keyof T> = K extends 'b' ? true : false; type RequiredIf<T> = { [K in keyof T]: T[K] } & { // 仅对符合条件的字段移除可选性 [K in keyof T as TestKey<T, K> extends true ? K : never]-?: T[K] }; type test = RequiredIf<{a: 1, b?: 2, c?: 3}>; // 结果:{a: 1, b: 2, c?: 3}
是否需要提交功能请求?
当前通过内置工具类型的组合已经能覆盖这类动态修饰符需求,虽然写法不如直接在类型分支中添加修饰符直观,但足够满足大多数场景。如果有更复杂的动态修饰需求(例如同时动态控制readonly和可选性的复杂场景),可以考虑向TypeScript官方提交功能请求,但针对当前的单一需求,必要性不高。
内容的提问来源于stack exchange,提问作者zedryas
相关产品推荐
相关产品推荐

