簡體   English   中英

從打字稿中的基類通用類推斷子類屬性類型

[英]Infer subclass property type from base class generic in typescript



    class A<T>
    {
        some: { [K in keyof T]: (x: T[K]) => T[K] }
    }

    interface IB {
        b: number
    }

    class B<T extends IB> extends A<T>
    {
        constructor()
        {
            super()

            /**
             * Type '{ b: (x: T["b"]) => number; }'
             * is not assignable to type '{ [K in keyof T]: (x: T[K]) => T[K]; }'.
             */
            this.some = {
                b: x => 2*x
            }
        }
    }

    interface IC {
        b: number
        c: boolean
    }

    class C<T extends IC> extends B<T>
    {
        constructor()
        {
            super()
            /**
             * Type '{ b: (x: T["b"]) => number; c: (x: T["c"]) => boolean; }'
             * is not assignable to type '{ [K in keyof T]: (x: T[K]) => T[K]; }'
             */
            this.some = {
                b: x => 4*x,
                c: x => !x
            }
        }
    }

你好。 我試圖在基類“ A”中設置通用約束,以自動推斷派生類中“某些”屬性的類型。 不幸的是,我不明白為什么會出現如上所述的TS錯誤。 從我的角度來看,一切似乎都還可以。

謝謝!

如果我這樣做,該怎么辦?

const b = new B<{ b: 3, z: string }>();

如您所見,我傳入了{ b: 3, z: string } ,這是可以接受的,因為它擴展了{ b: number } 所以這意味着b.some.b應該是(x: 3) => 3 這也意味着b.some.z應該是(x: string) => string B的實現是否是真的? 沒有; b.some.b實際上是(x: 3) => number ,而b.some.z是未定義的。 因此,編譯器警告您是有道理的。

首先,讓我們處理z: string問題。 也許在A您希望其中some的屬性是可選的,如下所示:

class A<T>
{
  some: {[K in keyof T]?: (x: T[K]) => T[K]}
}

這將使您的BC構造函數可以初始化some而不必了解額外的屬性。

現在,關於b: 3 如果您想允許某人擴展number ,那么唯一可以使用的安全方法就是身份驗證功能:

this.some = {};
this.some.b = x => x; // okay

但可能您不希望任何人傳遞比b類型更具體的number 不幸的是,沒有阻止它的好方法。 因此,很好地證明,用戶只能傳遞b可以為任何number類型。 在這種情況下,你只是需要告訴編譯器不要擔心,通過聲稱this是類型B<IB>

this.some = {};
(this as B<IB>).some.b = x => 2 * x; // okay

可以為您的C類進行類似的修復。 希望能有所幫助; 祝好運!

暫無
暫無

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

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