考虑以下事项:
export type JSONable = Record<string, string | number>
export type Processable = {
process(args?: JSONable): Promise<void>
}
abstract class AbstractTaskProcessor<T extends JSONable> implements Processable {
abstract process(args?: T): Promise<void>
}
这是我工作系统的一部分。但有时为了测试我想马上测试流程方法,所以我想添加一个像这样的静态辅助方法
abstract class AbstractTaskProcessor<T extends JSONable> implements Processable {
abstract process(args?: T): Promise<void>
static runNow(args?: T): Promise<void> {
const instance = new this()
return instance.process(args)
}
}
但我得到一个 TS2511: Cannot create an instance of an abstract class.
我希望 DSL 类似于......
MyTaskProcessor.runNow({accountId: 123123, accountName: 'Lorum' })
有没有人对此有好的模式?
我使用的是 TS 4.2
答案 0 :(得分:4)
如果您只是对@ccarton 显示的方式进行类型转换,您就可以使您的示例工作。但如果它仅用于测试并且您想保留 T extends JSONable
的类型信息,我建议为它编写一个函数,例如 this:
class MyTaskProcessor extends AbstractTaskProcessor<{test: number, test2: string}> {
process(args?: {test: number, test2: string}): Promise<void> {
return Promise.resolve();
}
}
type Processable<T> = {
process(args?: T): Promise<void>
}
export function runNow<T extends JSONable>(processorClass: new () => Processable<T>, args: T) {
const instance = new processorClass();
return instance.process(args)
}
runNow(MyTaskProcessor, {test: 5, test2: "hello"})
runNow(MyTaskProcessor, {test: 5, test2: 3}) // Type 'number' is not assignable to type 'string'
MyTaskProcessor.runNow({test: 5, test2: 3}) // no typesafety, no warning
使用@Linda Paiste 的精炼版进行更新
答案 1 :(得分:2)
从 Typescript 4.2 开始,现在支持抽象构造函数签名。请参阅:https://devblogs.microsoft.com/typescript/announcing-typescript-4-2/#abstract-construct-signatures
如果由于某种原因您无法升级,旧的解决方案需要常规构造函数签名和类型断言:
type JSONable = Record<string, string | number>
type Processable = {
process(args?: JSONable): Promise<void>
}
type ProcessableConstructor = { new (): Processable } // Constructor signature
abstract class AbstractTaskProcessor<T extends JSONable> implements Processable {
abstract process(args?: T): Promise<void>
static runNow<T extends JSONable> (args?: T): Promise<void> {
const instance = new (this as any as ProcessableConstructor)() // Type assertion
return instance.process(args)
}
}
class MyTaskProcessor extends AbstractTaskProcessor<JSONable> {
async process (args: JSONable) { return }
}
MyTaskProcessor.runNow({accountId: 123123, accountName: 'Lorum' })