簡體   English   中英

TypeScript:差異通用約束 VS 參數類型

[英]TypeScript: Difference Generic Constraints VS Parameter Type

我不明白通用約束和普通參數類型之間的區別。 在第一種情況下,我確實明白我不能調用 si.g() 因為我嚴格地將 si 鍵入為 SomeInterface 類型。 但是,在第二個示例中, S 擴展了 SomeInterface ,根據我的解釋,擴展意味着它需要具有 f() 但可以包含更多屬性。 但錯誤是一樣的。 為什么?

interface SomeInterface {
    f();
}

function test1(si: SomeInterface) {
    si.f()
    // si.g() -> Property 'g' does not exist on type 'SomeInterface'
}

function test2<S extends SomeInterface>(si: S) {
    si.f()
    // si.g() -> Property 'g' does not exist on type 'SomeInterface'
}

Typescript 需要檢查您傳遞的類型是否包含函數g 所以你需要做這樣的事情:

interface ExtendedInterface extends SomeInterface {
 g();
}

...

function test2<E extends ExtendedInterface>(ei: E) {
    si.f()
    si.g()
}

當然,你也可以這樣做:

function test3(ei: ExtendedInterface) {
    ei.g();
    ei.f();
}

這在功能上與帶有泛型的版本相同。

那么有什么區別呢? 這里沒有什么,但是泛型以更復雜的代碼為代價為您提供了更多的功能。 例如,泛型允許您聲明受另一個類型參數約束的類型參數。

...擴展意味着它需要有 f() 但可以包含更多屬性。 但錯誤是一樣的。 為什么?

因為它可能有也可能沒有更多的屬性,如果有,它們可能有任何名稱或任何類型。 TypeScript 不知道這些屬性是什么,所以在test2 ,TypeScript 只知道siSomeInterface

您首先說您不了解類型參數( <S extends SomeInterface>si: S )與僅將類型放在參數上( si: SomeInterface )之間的si: SomeInterface 類型參數讓你做更多有趣的事情,比如:

function pluck<Type extends object, Key extends keyof Type>(array: Type[], key: Key) {
    return array.map(element => element[key]);
}

const objects = [{a: 2, b: "s"}, {a: 3, b: "x"}];
const x = pluck(objects, "a"); // `x` is `number[]`
const y = pluck(objects, "b"); // `y` is `string[]`

游樂場鏈接

我可能弄錯了,但我認為如果沒有類型參數(或類型斷言),您就無法做到這一點。

暫無
暫無

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

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