TypeScript如何编写合并键值数组为精确类型对象的泛型函数
问题场景
现有一个将键数组与值数组合并为对象的函数,初始实现存在类型报错,代码如下:
function mergeToObject(keys: string[], values: string[]) { const object:? = {} for (let i = 0; i < keys.length; i++) { object[keys[i]] = values[i] // TypeScript在此处抛出类型错误 } return object }
函数预期运行效果:
mergeToObject(['a', 'b', 'c'], ['x', 'y', 'z']) // => { a: 'x', b: 'y', c: 'z' }
实际使用时keys参数始终传入常量表达式,不会传入运行时动态生成的值,需要通过泛型语法精确声明返回对象类型,自动识别传入的固定键名,具体类型要求:
const values = ['x', 'y', 'z'] // 传入['a','b','c']作为键时 const object = mergeToObject(['a', 'b', 'c'], values) // object期望类型为 { a: string, b: string, c: string } object.a // 类型校验通过 object.b // 类型校验通过 object.c // 类型校验通过 object.d // 类型校验报错 // 传入['e','f','g']作为键时 const object2 = mergeToObject(['e', 'f', 'g'], values) // object2期望类型为 { e: string, f: string, g: string } object2.e // 类型校验通过 object2.f // 类型校验通过 object2.g // 类型校验通过 object2.d // 类型校验报错
实现方案
要满足上述类型推导要求,核心逻辑如下:
- 给键参数添加字符串字面量泛型约束,通过
readonly修饰兼容常量数组传入,让TypeScript可以推导出传入的具体字面量键,而非宽泛的string类型 - 初始化空对象时使用类型断言绕开初始化阶段的索引赋值报错,返回值使用内置
Record工具类型,基于推导到的键泛型生成精确的对象类型
最终可直接使用的实现代码:
function mergeToObject<K extends string>( keys: readonly K[], values: string[] ): Record<K, string> { const object = {} as Record<K, string> for (let i = 0; i < keys.length; i++) { object[keys[i]] = values[i] } return object }
扩展说明:如果后续
values也固定传入常量数组,可以再增加一个值的泛型参数,进一步推导出每个键对应值的精确字面量类型,当前实现完全匹配需求中值为普通string[]的场景。
上述实现的类型校验效果完全符合预期:访问存在的键时TS正常放行,访问未定义的键时TS会直接抛出不存在该属性的类型错误。
内容的提问来源于stack exchange,提问作者user18458709
相关产品推荐
相关产品推荐

