You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:34:57