首页 > 解决方案 > 带有通用参数的 TypeScript InstanceType

问题描述

我正在构建一个库,它允许消费者为其提供构造函数/类,其实例将构成其公共成员之一。

对于一个简单的非泛型类,这可以正常工作,并且我们可以在库实例的公共接口上获得准确推断的智能感知和类型安全性:

class MyLibrary<TNewable extends new (...args: any[]) => any> {
    public foo: InstanceType<TNewable>;

    constructor(ConsumerNewable: TNewable) {
        this.foo = new ConsumerNewable();
    }
}

class ConsumerProvidedClass {}

const library = new MyLibrary(ConsumerProvidedClass);

library.foo // type: ConsumerProvidedClass

现在考虑这样一个场景,ConsumerProvidedClass它本身有一个通用参数,它定义了它的行为的某些方面。这对于这个问题并不重要,但实际用例是 RxJSSubject或者observable 的吞吐量类型BehaviorSubject在哪里。TThroughput因此,例如:

class ConsumerProvidedClass<TThroughput> { ... }

该库现在已扩展为允许使用者提供类型的“初始值”,该类型TModelConsumerProvidedClass在实例化时传递给它,并且也成为其吞吐量类型:

class MyLibrary<TNewable extends new (...args: any[]) => any, TModel> {
    public foo: InstanceType<TNewable>;

    constructor(ConsumerNewable: TNewable, initialValue: TModel) {
        this.foo = new ConsumerNewable(initialValue);
    }
}

class ConsumerProvidedClass<TThroughput> {}

class ConsumerProvidedModel {}

const library = new MyLibrary(ConsumerProvidedClass, new ConsumerProvidedModel());

library.foo // type: ConsumerProvidedClass<{}>

问题是属性上的智能感知.foo正确推断ConsumerProvidedClass不知道其通用吞吐量类型,并回退到<{}>.

我想看到的是:

library.foo // type: ConsumerProvidedClass<ConsumerProvidedModel>

TModel但这将依赖于能够InstanceType<TNewable>作为通用参数提供。我无法找到有关如何执行此操作的任何信息,或者是否确实有可能。理想情况下,我想做这样的事情:

public foo: (InstanceType<TNewable>)<TModel>;

但不幸的是,这不是有效的 TypeScript。

当然,我可以让消费者在实例化库时显式传递所有泛型类型,但我更希望一切都在可能的情况下进行推断,以获得更好的开发人员体验。

任何见解都非常感谢。也许还有另一种我想念的方法来解决这个问题。

标签: typescriptgenerics

解决方案


推荐阅读