如何在TypeScript中不使用Partial通过循环创建键来自列表的对象
解决方案
方案1:使用Object.fromEntries实现类Python字典推导写法
这是最贴合你Python写法的直接TS等价实现,TS 3.1及以上版本支持,无需中间Partial过渡,逻辑和字典推导完全一致:
// 先将键数组映射为 [键, 值] 元组数组,再直接转换为对象 const allPlanFeatures = Object.fromEntries( extensivePlanList.map(planHandle => [ planHandle, getFeaturesForPlan(planHandleToMonthly[planHandle], is4kEnabled, exportFlow) ] ) as Record<ExtensivePlanHandle, string[]>
如果你的extensivePlanList本身就是严格的ExtensivePlanHandle类型的完整枚举/联合数组,该写法完全类型安全。
方案2:封装泛型工具函数(重复场景推荐)
如果需要频繁初始化已知键的Record对象,可以封装通用泛型工具函数,使用时无需额外类型断言,自动推导正确类型:
// 通用工具函数,复用性强 function createRecord<K extends string | number | symbol, V>(keys: K[], getValue: (key: K) => V): Record<K, V> { return Object.fromEntries( keys.map(key => [key, getValue(key)]) ) as Record<K, V> } // 调用示例 const allPlanFeatures = createRecord(extensivePlanList, planHandle => getFeaturesForPlan(planHandleToMonthly[planHandle], is4kEnabled, exportFlow) )
该方案全程无Partial、无强制类型转换,TS可自动推导出allPlanFeatures为Record<ExtensivePlanHandle, string[]>类型。
方案3:指定reduce泛型参数(兼容低版本TS)
如果你的TS版本较低不支持Object.fromEntries,可以直接给reduce指定泛型参数,跳过Partial环节:
const allPlanFeatures = extensivePlanList.reduce<Record<ExtensivePlanHandle, string[]>>( (acc, planHandle) => { acc[planHandle] = getFeaturesForPlan(planHandleToMonthly[planHandle], is4kEnabled, exportFlow) return acc }, // 初始空对象直接断言为目标类型 {} as Record<ExtensivePlanHandle, string[]> )
只要你能保证extensivePlanList覆盖了ExtensivePlanHandle的所有取值,该写法完全安全。
原写法需要
Partial过渡的本质原因是空对象{}天然不符合完整Record的类型定义,上述方案的核心都是跳过空对象的过渡校验环节,只要运行时键是完整的,类型安全不受影响。
内容的提问来源于stack exchange,提问作者JoshMc
相关产品推荐
相关产品推荐

