[英]Overloading type with typescript
我有以下實現
export class DbService<T extends object> {
addOne<TKey extends keyof T>(table: TKey, object: T[TKey]) {
return this.db.table(String(table)).add(object);
}
}
當您將有效接口作為 T 時,它可以正常工作:
interface DbSchema {
users: User
}
var db = new DbService<DbSchema>();
// working fine here.
// It asks for 'users' key that matches the DbSchema
// And asks for User object implementation
db.addOne('users', { name: 'foo' });
但是現在我希望DbSchema
接口可以是可選的,並且您可以將任何鍵作為表。 所以我嘗試了以下重載方法:
addOne<TKey extends keyof T>(table: TKey, object: T[TKey]): T[TKey];
addOne<O extends object>(table: string, object: O): O;
addOne(table: any, object: any) {
return this.db.table(String(table)).add(object);
}
我可以說它部分工作,但 typescript 停止幫助我實現 object ,即使密鑰與DbSchema
匹配。
它開始很好,顯示來自DbSchema
的鍵:
但是當您開始編寫 object 時,它會丟失軌道並跳轉到第二個過載:
我能做些什么來幫助它嗎?
我認為您的問題是,一旦您鍵入{}
,這是一個與User
類型不匹配的空 object ,並且編譯器立即切換到另一個重載,因為"users"
匹配string
並且{}
匹配object
。
這里一種可能的解決方案是確保第二個重載不接受已知密鑰,如下所示:
addOne<TKey extends keyof T>(table: TKey, object: T[TKey]): T[TKey];
addOne<S extends string, O extends object>(table: S & Exclude<S, keyof T>, object: O): O;
addOne(table: any, object: any) {
return null!;
}
現在第二個重載的table
參數類型為S & Exclude<S, keyof T>
,其中Exclude<A, B>
是一種實用程序類型,它采用聯合類型A
並刪除任何可分配給B
的成員。 如果S
是與keyof T
不同的字符串,則S & Exclude<S, keyof T>
將是S & S
,即S
。 但是如果S
本身可以分配給keyof T
,那么S & Exclude<S, keyof T>
將是S & never
,也就是never
。
參數S
將被推斷為為table
傳入的字符串文字值。 這意味着只要table
不在keyof T
中,就會根據S
檢查table
,這很好。 但是如果table
在keyof T
中,則table
將與never
進行檢查,這是一個錯誤。 因此,一旦您在 for table
中傳遞"users"
之類的內容,編譯器就會確定它與第二個重載不匹配。 因此,當您正在鍵入{}
時,編譯器沒有理由切換到第二個重載,並且您會獲得所需的 IntelliSense:
希望這對你有用,或者至少給你一些想法。 祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.