TypeScript中能否访问数组类型元素标签并转换为对象类型?
带标签元组转同结构对象类型实现
完全可以实现,不需要手动编写重复的对象类型,TypeScript 4.1 及以上版本可以通过类型工具提取元组元素的标签,直接生成对应结构的对象类型。
类型实现代码
// 提取元组指定索引位置的元素标签 type GetTupleLabel<T extends readonly unknown[], I extends number> = (<U extends (x: never, ...args: { [K in keyof T]: [T[K]] }[number]) => void>() => U) extends (<U extends (x: never, ...args: infer P) => void>() => U) ? P[I] extends [infer _] ? P[I] extends Record<infer K, any> ? K & string : never : never : never; // 核心转换类型 type Transform<T extends readonly unknown[]> = { [K in keyof T as K extends `${infer Index extends number}` ? GetTupleLabel<T, Index> : never ]: T[K] };
效果验证
基础用例
type A = [a: number, b: string]; type B = Transform<A>; // 推导结果:{ a: number; b: string },完全符合预期
实际业务场景用例
完全匹配函数参数同步的需求:
const data: Transform<Parameters<typeof f>>[] = []; function f(a: number, b: string) { // 类型校验通过,属性名、类型完全和参数对应 data.push({ a, b }); // 以下错误写法会被TS直接拦截: // data.push({ a: 'str', b: 123 }); // 属性类型不匹配报错 // data.push({ a: 123 }); // 缺少属性b报错 // data.push({ a: 123, b: 'str', c: true }); // 多余属性c报错 }
兼容说明
- 支持可选参数、剩余参数的元组转换,比如
type C = Transform<[id: number, name?: string, ...tags: string[]]>会被推导为{ id: number; name?: string; tags: string[] } - 函数参数列表调整时,对应的
Transform<Parameters<typeof f>>类型会自动同步更新,不需要手动维护映射关系,彻底消除重复编码 - 要求TypeScript版本 >= 4.1,目前绝大多数前端项目的TS版本都满足该要求
内容的提问来源于stack exchange,提问作者Doofus
相关产品推荐
相关产品推荐

