TypeScript泛型设置映射类型值:如何重构WrapSet遍历属性
TypeScript 代码重构问题
给定以下 TypeScript 代码示例:
type Properties = { item0: { item0: string }; item1: { item1: string }; item2: { item2: string }; item3: { item3: string }; item4: { item4: string }; }; type Func<N extends keyof Properties> = ({}: Properties[N]) => number; const Wrap = <N extends keyof Properties>(inner: Func<N>): Func<N> => { return (v: Properties[N]) => inner(v) + 2; }; type FuncSet = { [Property in keyof Properties]: Func<Property> }; const WrapSet = (inner: FuncSet): FuncSet => { return { item0: Wrap(inner.item0), item1: Wrap(inner.item1), item2: Wrap(inner.item2), item3: Wrap(inner.item3), item4: Wrap(inner.item4), }; };
如何重构 WrapSet 函数,使其能够遍历 Properties 中的条目,无需显式指定每个 item?要求解决方案不绕过 TypeScript 类型系统。
解决方案
可以通过动态遍历对象键的方式实现,同时借助 TypeScript 的类型断言与推断保证类型安全,以下是两种可行方案:
方案一:for 循环遍历
const WrapSet = (inner: FuncSet): FuncSet => { const result: Partial<FuncSet> = {}; // 遍历所有键并断言为Properties的键类型 for (const key of Object.keys(inner) as Array<keyof Properties>) { result[key] = Wrap(inner[key]); } // 断言结果为完整的FuncSet类型 return result as FuncSet; };
关键说明
- 用
Object.keys(inner)获取所有键,通过类型断言缩小到Array<keyof Properties>,让 TypeScript 识别键的合法范围。 - 初始化
Partial<FuncSet>类型的临时对象,避免空对象不满足FuncSet完整结构的类型报错。 - 遍历赋值完成后,通过类型断言告知 TypeScript 临时对象已具备完整的
FuncSet结构。
方案二:Object.fromEntries 简洁实现
const WrapSet = (inner: FuncSet): FuncSet => { return Object.fromEntries( Object.entries(inner).map(([key, func]) => [ key, Wrap(func as Func<keyof Properties>) ]) ) as FuncSet; };
关键说明
- 用
Object.entries将对象转为键值对数组,再通过map对每个函数应用Wrap包装。 - 对
func做类型断言as Func<keyof Properties>,修正Object.entries返回的宽泛类型,确保与Wrap的参数类型匹配。 - 最后用
Object.fromEntries转回对象,并断言为FuncSet保证类型正确性。
两种方案均无需显式列出每个 item,且完全遵循 TypeScript 类型检查规则,未绕过类型系统。
内容的提问来源于stack exchange,提问作者Dave Butler
相关产品推荐
相关产品推荐

