【问题标题】:Typescript generics: Refer to class instead of instance打字稿泛型:引用类而不是实例
【发布时间】:2019-09-24 08:00:38
【问题描述】:

我有一种情况,我想在一组接口中使用泛型类型。我的公共接口接收泛型类型并将其传递给非导出的私有接口。在我的公共接口中,我想使用泛型类型T,但我希望它引用T实例。我想说它是T,这个类可以产生T 的实例。

尝试这个,我得到一个错误:

interface Car<T> {
  unit: T;
  progress: number;
}

export interface CarFactory<T> {
  cars: Car<T>[];
  // Type error: 'T' only refers to a type, but is being used as a value here.  TS2693
  blueprint: typeof T;
}

使用生成器函数有效。但随后我必须将其传递下去并暴露更多我想要避免的代码内部结构。

interface CarFactory<T> {
  blueprint: (args: any) => T;
}

我不能直接使用T,因为这会导致编译器认为它应该接收T 的实例,而不是类。这会触发 TS2740 错误。使用 T = CarModelT['constructor'] 作为 blueprint 类型有效,但前提是我像这样修补我的类:

class CarModel {
  public ['constructor']: typeof CarModel;
}

所以问题是:我怎样才能使用这样的泛型?使用T 和实际T 的两个实例?生成器函数或带有修补的T['constructor'] 是我唯一的选择吗?我是否需要传递另一个泛型类型U,类似于U = typeof T

【问题讨论】:

  • T 应该在Car&lt;T&gt; 中是什么?这是某种仅适用于给定类型的汽车,但我不确定这是否是您的意思。也许您甚至不需要 Car 的泛型。对我来说,interface Car 没有泛型,然后是 interface CarFactory&lt;T extends Car&gt; 之类的东西似乎更合乎逻辑,因为 CarFactory 将创建汽车。
  • 实例类型和类类型之间没有直接联系,如果这是你所追求的。有一个建议自动键入constructor,就像您在CarModel 中一样,但它尚未实现
  • 我意识到我在将代码转换为此处的示例时感到困惑。修正了我的问题,使其更加重要。抱歉不清楚!

标签: typescript generics


【解决方案1】:

你的意思是这样的吗?

给定一个类Cartype of the class itself(引用类的构造函数的符号Car)将是typeof Car。在CarFactory接口中,我们没有具体的类,所以我们可以使用type of the constructor functionnew (...args: any) =&gt; Tblueprint

export interface CarFactory<T> {
  cars: Car<T>[];
  // use a constructor function type here
  blueprint: new (...args: any) => T;
}

测试一下:

class CombiUnit {
  // your implementation of a car unit/model T goes here
}

type CombiUnitFactory = CarFactory<CombiUnit>;

// new (...args: any) => CombiUnit
type CombiUnitFactoryCtorFunction = CombiUnitFactory["blueprint"];

// some concrete factory
declare const t1: CombiUnitFactory;

const result = new t1.blueprint(); // const result: CombiUnit

Playground

【讨论】:

  • 是的!正是这样。 new (...args: any) =&gt; T 正是我想要的。非常感谢!
【解决方案2】:

typeof 运算符有效地返回一个值。写就够了

interface Car<T> {
  blueprint: T;
}

除此之外,我认为工厂类应该是静态的,因此不需要接口。你可以像这样创建一个静态汽车工厂类:

export class AutomobileFactory {
  static createCar<T>(): Car<T> {
    // create a concrete car implementation of the
    // generic type T instead of throwing an error
    throw new Error("Not implemented");
  }
}

【讨论】:

  • 我更新了我的示例和问题,以减少混淆并更直接地解释情况。不过谢谢你的回答!此外,为了避免创建带有运行时错误的静态方法,您可以使用abstract classes and methods
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2021-06-16
  • 2020-04-13
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 2018-04-27
相关资源
最近更新 更多