TypeScript泛型接口如何约束属性名并推导对应值类型
问题场景
初始定义的泛型接口如下,存在类型无法绑定的问题:
export interface Column<T> { field: string; columnFormatter?: (props: { value: any; // 目标:让该值类型和field指向的T属性类型一致 data: T; node: any; }) => void; }
需要实现两个类型约束:
field只能传入泛型T的合法属性名,传入不存在的属性时TS直接报错columnFormatter入参中的value,能根据当前传入的field自动推导为T中对应属性的类型
目标使用示例:
export interface IPurchase { id: string; name: string; purchaseDate: Date; } let doSomethingWithMyDate: (myDate: Date) => boolean = () => true; const columns: Array<Column<IPurchase>> = [ { field: "purchaseDate", // 仅允许传入IPurchase存在的属性 columnFormatter: ({ value }) => // value需自动推导为Date类型,可直接传参给接收Date的函数 doSomethingWithMyDate(value) } ];
实现方案
直接将Column定义为如下类型即可满足需求:
export type Column<T> = { [K in keyof T]: { field: K; columnFormatter?: (props: { value: T[K]; data: T; node: any; }) => void; } }[keyof T];
原理说明
keyof T会获取泛型T所有属性名的联合类型,从根源限制field的合法取值范围- 映射类型
[K in keyof T]会遍历T的每一个属性,为每个属性单独生成匹配的结构:field固定为当前属性名的字面量类型K,value通过索引访问类型T[K]直接取到K对应属性的类型,完成两者的类型绑定 - 末尾的
[keyof T]会取出映射类型中所有属性值的联合类型,TS会根据对象中传入的field字面量自动收窄到联合中对应的类型分支,自动推导value的正确类型,不需要额外手动标注类型。
内容的提问来源于stack exchange,提问作者Thorvarium
相关产品推荐
相关产品推荐

