簡體   English   中英

Typescript:了解聯合和交集類型

[英]Typescript: understanding union and Intersection types

我試圖對 typescript 中的 Union 和 Intersection 類型有一個直覺,但我無法弄清楚這種情況: Playground Link

interface A {
    a: number;
}

interface B{
    b: boolean;
}



type UnionCombinedType = A | B;
type IntersectionType = A & B;

const obj: UnionCombinedType = {
    a: 6,
    b: true,
}

const obj2: IntersectionType = {
    a: 6,
    b: true,
}

為什么我允許將兩個值都放在交集類型中? 兩個接口之間的交集是空的。 如果我將&閱讀為AND那么我很清楚為什么它允許我添加兩個道具,但是我應該閱讀| 關鍵字為OR ,我希望它允許我只分配ab但不能同時分配兩者。

有人可以給我一些關於這些類型的直覺嗎?

鑒於以下情況:

interface A {
    a: number;
    c: number;
}

interface B{
    b: boolean;
    c: number;
}

聯合類型A | B A | B可分配給AB 它必須具有來自AB (或兩者)的屬性

const oA: A | B = {
    a: 6,
    c: 6
}

const oB: A | B = {
    b: true,
    c: 6
}

const oC: A | B = {
    a: 6,
    b: true
    c: 6
}

但是像A | B這樣的類型有什么操作? A | B有嗎? 只有屬於AB的那些

oA.c = 1; // valid

交集類型A & B ,如果它可以分配給 A 和 B (因此必須具有 A 和 B 的屬性)。

const obj: A & B = {
    a: 6,
    b: true
}

更新

你問“為什么你的例子中的 A & B 可以使用 b 道具?它不能分配給類型 A”

這顯然不是真的。 任何具有 A 的所有屬性的類型都可以分配給 A。額外的屬性沒有害處:

const aAndExtraProp = {
  a: 6,
  d: 6
};

const ca0: A = aAndExtraProp;

您可能對 object 文字的過多屬性檢查感到困惑:

Object 文字在將它們分配給其他變量或將它們作為 arguments 傳遞時得到特殊處理並進行過多的屬性檢查。 如果 object 文字具有“目標類型”所沒有的任何屬性,您將收到錯誤消息:

const ca1: A = {
  a: 6,
  d: 6 //ERROR
};

從聯合類型接受什么的角度思考。 可以分配給字符串的一組事物 | number 字段是所有字符串的集合和所有數字的集合的並集。 可以分配給字符串和數字的一組東西什么都不是,因為在所有字符串的集合和所有數字的集合中沒有重疊。

我認為您將其描繪為字段上的集合運算符,而不是每種類型所代表的集合的集合運算符。

//////////////////////

這是數學術語:“類型”是其所有可能值的集合,例如 boolean = {true, false};。 現在類型 T 和 U 的並集是由 T 或 U 中的值組成的集合(即 T 與 U 合並); T 和 U 中值的類似交集(即它們的公共部分)。

如果成員在所有可能的值上,則該成員是可訪問的。 對於 union,類型 T|U 的值可能是 T 也可能是 U。我們不知道哪個是合法的,所以只有公共屬性是合法的。 如您所見,對類型的操作意味着對成員的不同但互補的操作。 這是德摩根定律的結果。

https://www.reddit.com/r/typescript/comments/9qduq3/why_is_type_intersection_called_like_that_its/

以下示例可以幫助您了解 TS 聯合和交叉點的工作原理:

interface A {
  a1: string,
  a2: string,
}

interface B {
  b1: string,
  b2: string;
}

type UnionAB = A | B;
type IntersectionAB = A & B;

const unionAB1: UnionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b1: 'xxx',
  b2: 'xxx',
};

const unionAB2: UnionAB = {
  a1: 'xxx',
  a2: 'xxx',
};

const unionAB3: UnionAB = {
  b1: 'xxx',
  b2: 'xxx',
};

// Error
// Property 'a1' does not exist on type 'B'.
console.log(unionAB3.a1);

const unionAB4: UnionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b2: 'xxx',
};

// Error
// Property 'b1' does not exist on type 'UnionAB'.
// Property 'b1' does not exist on type 'A'.
console.log(unionAB4.b1);


// Error
// Type '{ a1: string; b2: string; }' is not assignable to type 'UnionAB'.
// Property 'b1' is missing in type '{ a1: string; b2: string; }' but required in type 'B'.
const unionAB5: UnionAB = {
  a1: 'xxx',
  b2: 'xxx',
};

const intersectionAB1 : IntersectionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b1: 'xxx',
  b2: 'xxx',
};

// Error
// Type '{ a1: string; a2: string; b1: string; }' is not assignable to type 'IntersectionAB'.
// Property 'b2' is missing in type '{ a1: string; a2: string; b1: string; }' but required in type 'B'.
const intersectionAB2 : IntersectionAB = {
  a1: 'xxx',
  a2: 'xxx',
  b1: 'xxx',
};

// Error
// Type '{ a2: string; b1: string; b2: string; }' is not assignable to type 'IntersectionAB'.
// Property 'a1' is missing in type '{ a2: string; b1: string; b2: string; }' but required in type 'A'.
const intersectionAB3 : IntersectionAB = {
  a2: 'xxx',
  b1: 'xxx',
  b2: 'xxx',
};

想想你可以分配給這些類型,而不是相交和合並類型本身。

type I = string & number;
type U = string | number;

const i: I = 5;

失敗了,我們希望i以某種方式同時成為字符串和數字,但那是不可能的( I never這里)。

const u: U = 5;

u可以是字符串或數字,所以沒關系

回到你的例子:

const obj2: IntersectionType = {
    a: 6,
    b: true,
}

工作正常,因為 obj2 與IntersectionType (同時具有屬性ab )。 TypeScript 循環遍歷obj2中的屬性,發現IntersectionType的所有必要屬性都存在。

const obj: UnionCombinedType = {
    a: 6,
    b: true,
}

Typescript 看着obj ... obj是否具有A中所需的屬性? 是的。 TS就夠了。

如果您將屬性c添加到兩個對象,TS 將失敗,因為它對於這兩種類型都是未知屬性,但那是另一回事。

暫無
暫無

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

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