如何为含动态键且值类型各异的对象定义TypeScript类型?
解决TypeScript泛型User类型的映射类型报错问题
问题需求
想要创建一个泛型类型User,根据传入的泛型参数(前缀字符串或undefined)生成不同的对象键:
- 传入前缀如
"new"时,键为new__firstname、new__lastname、new__age - 传入
undefined时,直接使用firstname、lastname、age
其中firstname、lastname的值类型为string,age的值类型为number。
已实现工具类型GetFullKey:
type GetFullKey< TPrefix extends string | undefined, TKey extends string > = TPrefix extends string ? `${TPrefix}__${TKey}` : TKey;
尝试定义User类型时出现错误:
export type User<TPrefix extends string | undefined> = { [key in GetFullKey< TPrefix, "firstname" | "lastname" >]: string; [key in GetFullKey< TPrefix, "age" >]: number; };
报错信息:
"A mapped type may not declare properties or methods."
错误原因
TypeScript不允许在单个类型字面量中声明多个独立的映射类型(即多个[key in ...]结构),每个类型字面量只能包含一个映射类型,其余需为普通属性声明。
解决方案
以下两种方案均可解决该问题:
方案1:交叉类型合并映射类型
将两个独立的映射类型通过&交叉合并为一个整体类型:
type GetFullKey< TPrefix extends string | undefined, TKey extends string > = TPrefix extends string ? `${TPrefix}__${TKey}` : TKey; export type User<TPrefix extends string | undefined> = { [key in GetFullKey<TPrefix, "firstname" | "lastname">]: string; } & { [key in GetFullKey<TPrefix, "age">]: number; };
方案2:统一映射键与类型的联合
先定义键和对应类型的联合元组,再通过映射生成完整类型:
type GetFullKey< TPrefix extends string | undefined, TKey extends string > = TPrefix extends string ? `${TPrefix}__${TKey}` : TKey; type UserFields = ["firstname", string] | ["lastname", string] | ["age", number]; export type User<TPrefix extends string | undefined> = { [K in UserFields as GetFullKey<TPrefix, K[0]>]: K[1]; };
效果验证
// 无前缀的默认用户类型 type DefaultUser = User<undefined>; // 类型结构:{ firstname: string; lastname: string; age: number } // 带前缀的新用户类型 type NewUser = User<"new">; // 类型结构:{ new__firstname: string; new__lastname: string; new__age: number }
内容的提问来源于stack exchange,提问作者Mimoid
相关产品推荐
相关产品推荐

