I would like to have a type safe register function that registers a WorkerOf with two arguments and two generic types so that consumers have to register a ClassA with the corresponding WorkerOfA.
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);
In both cases I am getting the following typescript error:
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)
CodePudding user response:
Your generic constraints of the form T extends Constructor<T>
don't mean what you want them to mean. If you need T
to be a constructor type, T extends Constructor<any>
would be sufficient. Otherwise, T extends Constructor<T>
means that T
is a constructor type whose instances are themselves T
. So it's a constructor that constructs constructors that construct constructors that construct constructors that...