簡體   English   中英

typescript重載型

[英]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的鍵:

測試 1

但是當您開始編寫 object 時,它會丟失軌道並跳轉到第二個過載:

測試 2

我能做些什么來幫助它嗎?

我認為您的問題是,一旦您鍵入{} ,這是一個與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 ,這很好。 但是如果tablekeyof T中,則table將與never進行檢查,這是一個錯誤。 因此,一旦您在 for table中傳遞"users"之類的內容,編譯器就會確定它與第二個重載不匹配。 因此,當您正在鍵入{}時,編譯器沒有理由切換到第二個重載,並且您會獲得所需的 IntelliSense:

addOne 的良好 IntelliSense(表:“用戶”,對象:用戶)

希望這對你有用,或者至少給你一些想法。 祝你好運!

鏈接到代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM