如何配置TypeScript接口函数,使返回类型为数组元素指定字段类型?
TypeScript 泛型函数返回类型修正问题
原始接口定义
interface IFields { name: string, items: { id: number }[] }
需求说明
需要创建IRecord接口,其中的getSublistValue函数需满足:
- 仅允许传入
IFields中属于数组类型的键作为sublistId fieldId必须是该数组元素对象的键- 函数返回类型要对应
fieldId的类型(例如示例中传入id时返回number)
当前实现及问题
当前实现已满足参数校验要求,但返回类型为数组元素对象(如{id: number}),而非目标字段类型:
interface IRecord<T> { fn: <K extends keyof T>(x: { sublistId: T[K] extends object[]? K: never, fieldId: T[K] extends (infer U)[]? keyof U: never, line: number}) => T[K] extends (infer U)[] ? U : never }
修正方案
通过新增泛型参数关联fieldId与对应字段类型,调整返回类型为字段的具体类型:
interface IRecord<T> { getSublistValue: <K extends keyof T, F extends keyof (T[K] extends (infer U)[] ? U : never)>( x: { sublistId: T[K] extends object[] ? K : never; fieldId: F; line: number; } ) => T[K] extends (infer U)[] ? U[F] : never; }
修正说明
- 新增泛型参数
F,约束为当前sublistId对应数组元素对象的键,确保fieldId的合法性 - 返回类型从数组元素对象
U改为U[F],直接映射到fieldId对应的字段类型 - 明确
fieldId的类型为F,让TypeScript能精准关联sublistId和fieldId的类型依赖关系
验证示例
const record: IRecord<IFields> = { getSublistValue: (x) => { // 实际业务逻辑实现 return {} as any; } }; // 合法调用,返回类型为number const itemId = record.getSublistValue({ sublistId: 'items', fieldId: 'id', line: 0 }); // 以下调用会触发TypeScript类型错误: // 1. sublistId传入非数组类型的'name' // record.getSublistValue({ sublistId: 'name', fieldId: 'id', line: 0 }); // 2. fieldId传入数组元素不存在的键 // record.getSublistValue({ sublistId: 'items', fieldId: 'name', line: 0 });
内容的提问来源于stack exchange,提问作者EliBaum
相关产品推荐
相关产品推荐

