TypeScript如何基于属性值限制另一属性类型并实现泛型推断
解决方案
首先先给出通用的固定长度元组工具类型实现:
type Tuple<T, N extends number, R extends T[] = []> = R['length'] extends N ? R : Tuple<T, N, [...R, T]>;
TypeScript 暂不支持直接在标注泛型接口类型的变量赋值时,从赋值内容自动推断泛型参数,你可以用以下两种常用方案实现需求:
方案1:泛型辅助函数(推荐)
利用 TypeScript 函数调用时的自动泛型推断能力,无需手动传入泛型参数即可完成校验:
// 原有泛型接口保持不变 interface Rating<T extends 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10> { maxRating: T; exampleResults: Tuple<number, T>; } // 新增泛型工具函数 function defineRating<T extends 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10>(rating: Rating<T>) { return rating; } // 直接使用,TypeScript 会根据maxRating自动推断泛型参数,校验exampleResults长度 const rating = defineRating({ maxRating: 5, exampleResults: [0, 0, 0, 1, 4], });
如果exampleResults的长度和maxRating取值不匹配,TypeScript 会直接抛出类型错误。
方案2:预生成联合类型
如果不想引入额外的工具函数,可以预先生成所有可能的Rating场景的联合类型,直接标注类型即可使用:
type MaxRating = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; type Rating = { [T in MaxRating]: { maxRating: T; exampleResults: Tuple<number, T>; } }[MaxRating]; // 直接标注类型使用,无需传入泛型参数 const rating: Rating = { maxRating: 5, exampleResults: [0, 0, 0, 1, 4], };
该方案的优势是使用时更简洁,不需要调用函数,弊端是如果后续需要扩展maxRating的取值范围,需要同步修改MaxRating联合类型。
内容的提问来源于stack exchange,提问作者senky
相关产品推荐
相关产品推荐

