我想要一個型別安全的注冊函式,它注冊一個帶有兩個引數和兩個泛型型別的 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)
uj5u.com熱心網友回復:
您對表單的一般約束T extends Constructor<T>并不意味著您想要它們的意思。如果您需要T成為建構式型別,T extends Constructor<any>就足夠了。否則,T extends Constructor<T>意味著它T是一個建構式型別,其實體是它們本身T。所以它是一個構造器構造構造器構造構造器構造構造器......??。
對于您提供的示例,您甚至不需要T extends Constructor<any>. 相反,讓我們T成為任意型別,并讓register()'_pyd引數為 type Constructor<T>,而_wkris 為 type WorkerConstructor<T>。也就是說,我們希望以下代碼是良好型別的:
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>
看起來不錯!
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/482085.html
上一篇:更改引數引數涉及的泛型
