如何在TypeScript泛型类构造函数中从接口推断泛型类型?
泛型类自动推断类型参数的问题与解决方法
需求
我正尝试设计一个泛型类D,希望类型A和R能从构造函数的第一个参数(接口I<A, R>的某个实现类的实例)中自动推断出来。
最初的尝试与错误
最初定义的泛型类D如下:
class D< C extends I<A, R>, A extends C extends I<infer A, infer R> ? A : never, R extends C extends I<infer A, infer R> ? R : never, > {}
原本期望TypeScript能从第一个参数自动推断A和R——例如当C实现I<number, string>时,A会被推断为number,R会被推断为string。
但实际遇到了类型参数循环约束错误(Type parameter 'A' has a circular constraint.(2313)和Type parameter 'R' has a circular constraint.(2313))。
测试代码中的问题
测试代码如下:
interface I<A, R> { a: A; r: R; } class C implements I<number, string> { a: number; r: string; } class D<C extends I<A, R>, A, R> { constructor(c: C, a: NoInfer<A>) {} getResult(): R { return void 0 as unknown as R; } } const c = new C(); const d1 = new D(c, 1); // 预期:d1类型应为D<C, number, string>,但实际推断为unknown const d2 = new D(c, "1"); // 预期:因"1"不是number类型报错,但未触发错误 const r1 = d1.getResult(); // 预期:r1类型应为string,但实际推断为unknown const array: D<C>[] = []; // 期望D能直接从第一个参数推断A和R,无需手动指定
存在的问题:
d1的类型被推断为unknown,而非预期的D<C, number, string>d2传入字符串"1"未触发类型不匹配报错r1的类型被推断为unknown,而非预期的string- 无法直接以
D<C>[]的形式定义数组,期望D能自动从第一个参数推断A和R
解决方案
感谢@Alexander Nenashev的帮助,最终解决方案如下:
type inferC<C> = (C extends I<infer A, infer R> ? { A: A; R: R } : never); type inferA<C> = inferC<C>['A']; type inferR<C> = inferC<C>['R']; class D<C extends I<any, any>, A extends inferA<C> = inferA<C>, R extends inferR<C> = inferR<C>> { constructor(c: C, a: NoInfer<A>) { } getResult(): R { return void 0 as unknown as R; } }
内容的提问来源于stack exchange,提问作者Megaman
相关产品推荐
相关产品推荐

