A 类型的 Typescript 泛型是 Class,B 是实现接口 <A> 的 class
Typescript generics for type A is a Class and B is a class that implements Interface<A>
我想要一个类型安全的注册函数,它注册一个带有两个参数和两个泛型类型的 WorkerOf,这样消费者就必须用相应的 WorkerOfA 注册一个 ClassA。
type Worker<Payload> = { exec: (payload: Payload) => Promise<void> };
type Constructor<Payload> = new (...args: any[]) => Payload;
type WorkerConstructor<Payload extends Constructor<Payload>> = new (
...args: any[]
) => Worker<Payload>;
function register<Payload extends Constructor<Payload>>(
_pyd: Payload,
_wkr: WorkerConstructor<Payload>
) {}
class PayloadOne {}
class PayloadTwo {}
class WorkerOne implements Worker<PayloadOne> {
constructor() {}
async exec(_payload: PayloadOne): Promise<void> {}
}
// Expected to work because WorkerOne implements Worker<PayloadOne>
register(PayloadOne, WorkerOne);
// Expected to fail because WorkerOne doesn't implements Worker<PayloadTwo>
register(PayloadTwo, WorkerOne);
在这两种情况下,我都收到以下打字稿错误:
Argument of type 'typeof PayloadOne' is not assignable to parameter of type 'Constructor<typeof PayloadOne>'. Property 'prototype' is missing in type 'PayloadOne' but required in type 'typeof PayloadOne'.ts(2345)
您的 generic constraints 形式 T extends Constructor<T>
并不是您希望他们表达的意思。如果您需要 T
作为构造函数类型,T extends Constructor<any>
就足够了。否则,T extends Constructor<T>
意味着 T
是一个构造函数类型,其实例本身就是 T
。所以它是一个构造函数,构造函数,构造函数,构造函数,构造函数,...
对于您提供的示例,您甚至不需要 T extends Constructor<any>
。相反,让 T
是任意类型,并且 register()
的 _pyd
参数是 Constructor<T>
类型,而 _wkr
是 [=25] 类型=].也就是说,我们希望下面的代码是 well-typed:
new _wkr().exec(new _pyd())
看起来像这样:
type Worker<T> = { exec: (payload: T) => Promise<void> };
type Constructor<T> = new (...args: any[]) => T;
type WorkerConstructor<T> = new (...args: any[]) => Worker<T>;
function register<T>(
_pyd: Constructor<T>,
_wkr: WorkerConstructor<T>
) { }
所有编译都很好,请注意 T
不受任何限制。让我们确保它在您调用 register()
:
时有效
class PayloadOne { a = 1 }
class PayloadTwo { b = 2 }
class WorkerOne implements Worker<PayloadOne> {
constructor() { }
async exec(_payload: PayloadOne): Promise<void> { }
}
register(PayloadOne, WorkerOne); // okay
register(PayloadTwo, WorkerOne); // error
// Argument of type 'typeof PayloadTwo' is not assignable
// to parameter of type 'Constructor<PayloadOne>
看起来不错!
我想要一个类型安全的注册函数,它注册一个带有两个参数和两个泛型类型的 WorkerOf,这样消费者就必须用相应的 WorkerOfA 注册一个 ClassA。
type Worker<Payload> = { exec: (payload: Payload) => Promise<void> };
type Constructor<Payload> = new (...args: any[]) => Payload;
type WorkerConstructor<Payload extends Constructor<Payload>> = new (
...args: any[]
) => Worker<Payload>;
function register<Payload extends Constructor<Payload>>(
_pyd: Payload,
_wkr: WorkerConstructor<Payload>
) {}
class PayloadOne {}
class PayloadTwo {}
class WorkerOne implements Worker<PayloadOne> {
constructor() {}
async exec(_payload: PayloadOne): Promise<void> {}
}
// Expected to work because WorkerOne implements Worker<PayloadOne>
register(PayloadOne, WorkerOne);
// Expected to fail because WorkerOne doesn't implements Worker<PayloadTwo>
register(PayloadTwo, WorkerOne);
在这两种情况下,我都收到以下打字稿错误:
Argument of type 'typeof PayloadOne' is not assignable to parameter of type 'Constructor<typeof PayloadOne>'. Property 'prototype' is missing in type 'PayloadOne' but required in type 'typeof PayloadOne'.ts(2345)
您的 generic constraints 形式 T extends Constructor<T>
并不是您希望他们表达的意思。如果您需要 T
作为构造函数类型,T extends Constructor<any>
就足够了。否则,T extends Constructor<T>
意味着 T
是一个构造函数类型,其实例本身就是 T
。所以它是一个构造函数,构造函数,构造函数,构造函数,构造函数,...
对于您提供的示例,您甚至不需要 T extends Constructor<any>
。相反,让 T
是任意类型,并且 register()
的 _pyd
参数是 Constructor<T>
类型,而 _wkr
是 [=25] 类型=].也就是说,我们希望下面的代码是 well-typed:
new _wkr().exec(new _pyd())
看起来像这样:
type Worker<T> = { exec: (payload: T) => Promise<void> };
type Constructor<T> = new (...args: any[]) => T;
type WorkerConstructor<T> = new (...args: any[]) => Worker<T>;
function register<T>(
_pyd: Constructor<T>,
_wkr: WorkerConstructor<T>
) { }
所有编译都很好,请注意 T
不受任何限制。让我们确保它在您调用 register()
:
class PayloadOne { a = 1 }
class PayloadTwo { b = 2 }
class WorkerOne implements Worker<PayloadOne> {
constructor() { }
async exec(_payload: PayloadOne): Promise<void> { }
}
register(PayloadOne, WorkerOne); // okay
register(PayloadTwo, WorkerOne); // error
// Argument of type 'typeof PayloadTwo' is not assignable
// to parameter of type 'Constructor<PayloadOne>
看起来不错!