TypeScript泛型获取属性类型报错问题求助
解决TypeScript中根据对象属性键推导对应类型字段的问题
要实现根据name对应的T属性类型自动推导type字段的类型,你需要让name和type在类型层面建立绑定关系,而不是使用松散的联合类型。以下是可行的解决方案:
正确实现代码
interface Req { stringField: string; dateField: string; numberField: number; } // 单个Field类型,用泛型K绑定具体的属性键 type Field<T, K extends keyof T> = { name: K; // 根据T[K]的类型推导type的可选值 type: T[K] extends number ? 'number' : T[K] extends string ? 'string' | 'date' : never; }; // 生成所有合法的Field联合类型 type AllFields<T> = { [K in keyof T]: Field<T, K> }[keyof T]; // 使用联合类型数组,TypeScript会自动校验每个元素的合法性 const arr: AllFields<Req>[] = [ { name: 'stringField', type: 'string' }, { name: 'dateField', type: 'date' }, { name: 'numberField', type: 'number' }, // 以下写法会触发类型错误,符合预期 // { name: 'stringField', type: 'number' }, // { name: 'numberField', type: 'string' } ];
原写法问题分析
Type1的语法错误:
T.Field<T>['name']是非法语法,T是类型而非命名空间/对象,不能通过.访问内部类型,因此即使添加@ts-ignore也无法彻底消除错误。Type2的逻辑缺陷:
Field<T>['name']本质是keyof T(所有属性键的联合),因此T[Field<T>['name']]等价于T[keyof T],即Req所有属性类型的联合(string | number)。此时(string | number) extends number的结果为false,导致type永远被推导为'string'|'date',无法匹配numberField的场景。
方案核心思路
通过引入泛型参数K,将name的具体键与type的推导逻辑绑定:每个Field<T, K>实例中,name固定为K,type则严格根据T[K]的类型生成对应可选值。AllFields<T>通过映射类型遍历所有属性键,生成所有合法的Field类型联合,确保数组中每个元素的name和type始终匹配。
内容的提问来源于stack exchange,提问作者guang y
相关产品推荐
相关产品推荐

