TypeScript中如何基于元组对象键值映射对应类型?
TypeScript元组到精准键值类型的映射实现
当然可以实现元组到精准键值类型的映射,核心是利用TypeScript的映射类型重映射(TypeScript 4.1+支持)来逐个处理元组中的元素,避免类型合并。
实现步骤
- 定义类型映射表
先把字符串类型标识映射到对应的TypeScript基础类型:
type TypeMap = { string: string; number: number; // 可按需扩展其他类型,比如boolean、date等 };
- 实现元组到对象的泛型类型
通过映射类型遍历元组的每个元素,提取name作为键,再通过TypeMap映射对应的类型:
type TupleToObject<T extends readonly { name: string; type: keyof TypeMap }[]> = { // 遍历元组的每个元素,用as重映射键为元素的name属性 [K in T[number] as K['name']]: TypeMap[K['type']]; };
验证示例
用你提供的输入测试:
const input = [ { name: "foo", type: "string" }, { name: "bar", type: "number" } ] as const; type ExpectedOutput = TupleToObject<typeof input>; // 类型完全符合预期:{ foo: string; bar: number; }
为什么之前的实现会合并类型?
如果直接取T[number]['type'],TypeScript会把元组中所有元素的type合并成联合类型(string | number)。而上面的方式是逐个处理元组中的每个元素,为每个元素单独生成键和对应的精准类型,不会出现类型合并的问题。
结合Zod Schema的扩展实现
针对你构建库生成Zod校验schema的需求,可以进一步写一个工具函数,同时保留类型推导:
import { z } from "zod"; function createZodSchema<T extends readonly { name: string; type: keyof TypeMap }[]>(fields: T) { const schemaEntries = fields.map(field => { // 根据type匹配对应的Zod类型 const zodType = field.type === 'string' ? z.string() : field.type === 'number' ? z.number() : z.unknown(); // 兜底,可扩展其他类型 return [field.name, zodType] as const; }); // 断言返回的schema类型为TupleToObject<T>对应的Zod类型 return z.object(Object.fromEntries(schemaEntries)) as z.ZodType<TupleToObject<T>>; } // 使用示例 const userSchema = createZodSchema(input); const validatedData = userSchema.parse({ foo: "test", bar: 42 }); // validatedData的类型自动推导为:{ foo: string; bar: number; }
内容的提问来源于stack exchange,提问作者Zuri Klaschka
相关产品推荐
相关产品推荐

