我正在构建一个库,该库允许消费者向其提供构造函数/类,该构造函数/类的实例将构成其公共成员之一。
对于一个简单的非泛型类,它可以正常工作,并且我们可以在库实例的公共接口上获得准确的推断智能和类型安全性:
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
本身具有一个通用参数,该参数定义了其行为的某些方面。这个问题并不重要,但是实际用例是RxJS Subject
或BehaviorSubject
,其中TThroughput
是可观察对象的吞吐量类型。因此,例如:
class ConsumerProvidedClass<TThroughput> { ... }
现在扩展了该库,以允许使用者提供类型为TModel
的“初始值”,该值将在实例化时传递给ConsumerProvidedClass
,并成为其吞吐量类型:
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
上的intellisense可以正确推断ConsumerProvidedClass
,但不知道其通用吞吐量类型,并退回到<{}>
。 / p>
我想看的是:
library.foo // type: ConsumerProvidedClass<ConsumerProvidedModel>
但这将依赖于能够向TModel
提供InstanceType<TNewable>
作为通用参数。我没有找到任何有关如何执行此操作的信息,或者是否确实有可能。理想情况下,我想做这样的事情:
public foo: (InstanceType<TNewable>)<TModel>;
但是不幸的是,这不是有效的TypeScript。
当然,我可以让使用者在实例化库时显式传递所有泛型类型,但是我更希望在所有可能的地方进行推断,以获得更好的开发人员体验。
任何见解都值得赞赏。也许还有另一种我想念的方式。