如何实现可指定填充属性的TypeScript User泛型类型?
实现支持部分填充属性的泛型User类型
首先给出基础接口定义:
interface Tenant { id: number; name: string; } interface Server { id: number; location: string; ip: string; }
需求说明
需要定义泛型User类型,满足:
- 默认状态下
tenant和server属性类型为number(未填充) - 可单独指定某一个或多个属性填充为对应对象类型,支持以下用法:
User:tenant和server均为numberUser<{ tenant: Tenant }>:tenant为Tenant,server仍为numberUser<{ tenant: Tenant; server: Server }>:两者均为对应对象类型
原有方案的问题
之前的实现通过强制泛型参数继承包含两个属性的UserPopulate接口,导致必须同时指定tenant和server或都不指定,无法单独配置部分填充属性。
可行实现方案
方案一:基于Partial泛型与条件类型
通过可选属性的泛型参数结合条件类型推导实现灵活的部分填充:
type User<Populate extends Partial<{ tenant: Tenant; server: Server }> = {}> = { id: number; name: string; tenant: Populate extends { tenant: infer T } ? T : number; server: Populate extends { server: infer T } ? T : number; };
方案说明
- 泛型参数
Populate使用Partial包裹,允许只传入部分属性(空对象对应默认未填充状态) - 利用条件类型判断:若
Populate包含目标属性,则取其指定类型;否则默认使用number
使用示例
// 默认情况:tenant和server均为number const user: User = { id: 1, name: "张三", tenant: 1001, server: 2001 }; // 仅填充tenant为Tenant类型 const user2: User<{ tenant: Tenant }> = { id: 2, name: "李四", tenant: { id: 1001, name: "租户A" }, server: 2001 }; // 同时填充tenant和server为对应对象类型 const user3: User<{ tenant: Tenant; server: Server }> = { id: 3, name: "王五", tenant: { id: 1001, name: "租户A" }, server: { id: 2001, location: "北京", ip: "192.168.1.1" } };
方案二:基于属性名联合类型
这种写法通过指定要填充的属性名联合类型实现,语义更直观:
type UserPopulateOptions = { tenant: Tenant; server: Server }; type User<Populate extends keyof UserPopulateOptions = never> = { id: number; name: string; } & { [K in keyof UserPopulateOptions]: K extends Populate ? UserPopulateOptions[K] : number; };
使用示例
// 默认情况:tenant和server均为number const user: User = { id: 1, name: "张三", tenant: 1001, server: 2001 }; // 仅填充tenant const user2: User<'tenant'> = { id: 2, name: "李四", tenant: { id: 1001, name: "租户A" }, server: 2001 }; // 同时填充tenant和server const user3: User<'tenant' | 'server'> = { id: 3, name: "王五", tenant: { id: 1001, name: "租户A" }, server: { id: 2001, location: "北京", ip: "192.168.1.1" } };
你可以根据业务场景的语义偏好选择合适的方案。
内容的提问来源于stack exchange,提问作者Arūnas Smaliukas
相关产品推荐
相关产品推荐

