日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
同事看完這幾道題,發(fā)現(xiàn) TS 交叉類(lèi)型竟還沒(méi)入門(mén)!
// 非對(duì)象類(lèi)型交叉運(yùn)算
type N0 = string & number;
type N1 = any & 1;
type N2 = any & never;

// 對(duì)象類(lèi)型交叉運(yùn)算
type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };

type AB = A & B;
type BC = B & C;

// 函數(shù)類(lèi)型交叉運(yùn)算
type F1 = (a: string, b: string) => void;
type F2 = (a: number, b: number) => void;

type Fn = F1 & F2

在學(xué)習(xí) TypeScript 的過(guò)程中,你可以把類(lèi)型理解成一系列值的集合。比如,你可以把數(shù)字類(lèi)型看作是所有數(shù)字的集合,1.0、68 就屬于這個(gè)集合中,而 "阿寶哥" 就不屬于這個(gè)集合,因?yàn)樗鼘儆谧址?lèi)型。

新源網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)自2013年創(chuàng)立以來(lái)到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。

同樣,對(duì)于對(duì)象類(lèi)型來(lái)說(shuō),我們也可以把它理解成對(duì)象的集合。比如以上代碼中 Point 類(lèi)型表示含有 x 和 y 屬性,且屬性值的類(lèi)型都是 number 類(lèi)型對(duì)象的集合。而 Named 類(lèi)型表示含有 name 屬性且屬性值的類(lèi)型是 string 類(lèi)型對(duì)象的集合。

interface Point {
x: number;
y: number;
}

interface Named {
name: string;
}

在集合論中,假設(shè) A,B 是兩個(gè)集合,由所有屬于集合 A 且屬于集合 B 的元素所組成的集合,叫做集合 A 與集合 B 的交集。

當(dāng)我們對(duì) Point 類(lèi)型和 Named 類(lèi)型進(jìn)行交集運(yùn)算,就會(huì)產(chǎn)生新的類(lèi)型。該類(lèi)型中所包含的對(duì)象既屬于 Point 類(lèi)型,又屬于 Named 類(lèi)型。

在 TypeScript 中為我們提供了交叉運(yùn)算符,來(lái)實(shí)現(xiàn)對(duì)多種類(lèi)型進(jìn)行交叉運(yùn)算,所產(chǎn)生的新類(lèi)型也被稱(chēng)為交叉類(lèi)型。

下面我們來(lái)簡(jiǎn)單介紹一下交叉運(yùn)算符,該運(yùn)算符滿足以下這些特性:

  • 唯一性:A & A 等價(jià)于 A
  • 滿足交換律:A & B 等價(jià)于 B & A
  • 滿足結(jié)合律:(A & B) & C 等價(jià)于 A & (B & C)
  • 父類(lèi)型收斂:如果 B 是 A 的父類(lèi)型,則 A & B 將被收斂成 A 類(lèi)型
type A0 = 1 & number; // 1
type A1 = "1" & string; // "1"
type A2 = true & boolean; // true

type A3 = any & 1; // any
type A4 = any & boolean; // any
type A5 = any & never; // never

在以上代碼中,any 類(lèi)型和 never 類(lèi)型比較特殊。除了 never 類(lèi)型之外,任何類(lèi)型與 any 類(lèi)型進(jìn)行交叉運(yùn)算的結(jié)果都是 any 類(lèi)型。

介紹完交叉運(yùn)算符之后,我們來(lái)看一下對(duì) Point 類(lèi)型和 Named 類(lèi)型進(jìn)行交叉運(yùn)算后,將產(chǎn)生什么樣的類(lèi)型?

interface Point {
x: number;
y: number;
}

interface Named {
name: string;
}

type NamedPoint = Point & Named
// {
//. x: number;
//. y: number;
//. name: string;
//. }

在以上代碼中,新產(chǎn)生的 NamedPoint 類(lèi)型將會(huì)同時(shí)包含 x、y 和 name 屬性。但如果進(jìn)行交叉運(yùn)算的多個(gè)對(duì)象類(lèi)型中,包含相同的屬性但屬性的類(lèi)型不一致結(jié)果又會(huì)是怎樣呢?

interface X {
c: string;
d: string;
}

interface Y {
c: number;
e: string
}

type XY = X & Y;
type YX = Y & X;

在以上代碼中,接口 X 和接口 Y 都含有一個(gè)相同的 c 屬性,但它們的類(lèi)型不一致。對(duì)于這種情況,此時(shí) XY 類(lèi)型或 YX 類(lèi)型中 c 屬性的類(lèi)型是不是可以是 string 或 number 類(lèi)型呢?下面我們來(lái)驗(yàn)證一下:

let p: XY = { c: "c", d: "d", e: "e" }; // Error
let q: YX = { c: 6, d: "d", e: "e" }; // Error

為什么接口 X 和接口 Y 進(jìn)行交叉運(yùn)算后,c 屬性的類(lèi)型會(huì)變成 never 呢?這是因?yàn)檫\(yùn)算后 c 屬性的類(lèi)型為 string & number,即 c 屬性的類(lèi)型既可以是 string 類(lèi)型又可以是 number 類(lèi)型。很明顯這種類(lèi)型是不存在的,所以運(yùn)算后 c 屬性的類(lèi)型為 never 類(lèi)型。

在前面示例中,剛好接口 X 和接口 Y 中 c 屬性的類(lèi)型都是基本數(shù)據(jù)類(lèi)型。那么如果不同的對(duì)象類(lèi)型中含有相同的屬性,且屬性類(lèi)型是非基本數(shù)據(jù)類(lèi)型的話,結(jié)果又會(huì)是怎樣呢?我們來(lái)看個(gè)具體的例子:

interface D { d: boolean; }
interface E { e: string; }
interface F { f: number; }

interface A { x: D; }
interface B { x: E; }
interface C { x: F; }

type ABC = A & B & C;

let abc: ABC = { // Ok
x: {
d: true,
e: '阿寶哥',
f: 666
}
};

由以上結(jié)果可知,在對(duì)多個(gè)類(lèi)型進(jìn)行交叉運(yùn)算時(shí),若存在相同的屬性且屬性類(lèi)型是對(duì)象類(lèi)型,那么屬性會(huì)按照對(duì)應(yīng)的規(guī)則進(jìn)行合并。

但需要注意的是,在對(duì)對(duì)象類(lèi)型進(jìn)行交叉運(yùn)算的時(shí)候,如果對(duì)象中相同的屬性被認(rèn)為是可辨識(shí)的屬性,即屬性的類(lèi)型是字面量類(lèi)型或字面量類(lèi)型組成的聯(lián)合類(lèi)型,那么最終的運(yùn)算結(jié)果將是 never 類(lèi)型:

type A = { kind: 'a', foo: string };
type B = { kind: 'b', foo: number };
type C = { kind: 'c', foo: number };

type AB = A & B; // never
type BC = B & C; // never

在以上代碼中,A、B、C 三種對(duì)象類(lèi)型都含有 kind 屬性且屬性的類(lèi)型都是字符串字面量類(lèi)型,所以 AB 類(lèi)型和 BC 類(lèi)型最終都是 never 類(lèi)型。接下來(lái),我們來(lái)繼續(xù)看個(gè)例子:

type Foo = {
name: string,
age: number
}

type Bar = {
name: number,
age: number
}

type Baz = Foo & Bar
// {
//. name: never;
//. age: number;
// }

在以上代碼中,Baz 類(lèi)型是含有 name 屬性和 age 屬性的對(duì)象類(lèi)型,其中 name 屬性的類(lèi)型是 never 類(lèi)型,而 age 屬性的類(lèi)型是 number 類(lèi)型。

但如果把 Foo 類(lèi)型中 name 屬性的類(lèi)型改成 boolean 類(lèi)型的話,Baz 類(lèi)型將會(huì)變成 never 類(lèi)型。這是因?yàn)?boolean 類(lèi)型可以理解成由 true 和 false 字面量類(lèi)型組成的聯(lián)合類(lèi)型。

type Foo = {
name: boolean, // true | false
age: number
}

type Bar = {
name: number,
age: number
}

type Baz = Foo & Bar // never

其實(shí)除了對(duì)象類(lèi)型可以進(jìn)行交叉運(yùn)算外,函數(shù)類(lèi)型也可以進(jìn)行交叉運(yùn)算:

type F1 = (a: string, b: string) => void;  
type F2 = (a: number, b: number) => void;

let f: F1 & F2 = (a: string | number, b: string | number) => { };
f("hello", "world"); // Ok
f(1, 2); // Ok
f(1, "test"); // Error

對(duì)于以上代碼中的函數(shù)調(diào)用語(yǔ)句,只有 f(1, "test") 的調(diào)用語(yǔ)句會(huì)出現(xiàn)錯(cuò)誤,其對(duì)應(yīng)的錯(cuò)誤信息如下:

沒(méi)有與此調(diào)用匹配的重載。
第 1 個(gè)重載(共 2 個(gè)),“(a: string, b: string): void”,出現(xiàn)以下錯(cuò)誤。
類(lèi)型“number”的參數(shù)不能賦給類(lèi)型“string”的參數(shù)。
第 2 個(gè)重載(共 2 個(gè)),“(a: number, b: number): void”,出現(xiàn)以下錯(cuò)誤。
類(lèi)型“string”的參數(shù)不能賦給類(lèi)型“number”的參數(shù)。ts(2769)

根據(jù)以上的錯(cuò)誤信息,我們可以了解到 TypeScript 編譯器會(huì)利用函數(shù)重載的特性來(lái)實(shí)現(xiàn)不同函數(shù)類(lèi)型的交叉運(yùn)算,要解決上述問(wèn)題,我們可以在定義一個(gè)新的函數(shù)類(lèi)型 F3,具體如下:

type F1 = (a: string, b: string) => void;  
type F2 = (a: number, b: number) => void;
type F3 = (a: number, b: string) => void;

let f: F1 & F2 & F3 = (a: string | number, b: string | number) => { };
f("hello", "world"); // Ok
f(1, 2); // Ok
f(1, "test"); // Ok

掌握了交叉類(lèi)型之后,在結(jié)合往期文章中介紹的映射類(lèi)型,我們就可以根據(jù)工作需要實(shí)現(xiàn)一些自定義工具類(lèi)型了。比如實(shí)現(xiàn)一個(gè) PartialByKeys 工具類(lèi)型,用于把對(duì)象類(lèi)型中指定的 keys 變成可選的。

type User = {
id: number;
name: string;
age: number;
}

type PartialByKeys = Simplify<{
[P in K]?: T[P]
} & Pick>>

type U1 = PartialByKeys
type U2 = PartialByKeys

那么如果讓你實(shí)現(xiàn)一個(gè) RequiredByKeys 工具類(lèi)型,用于把對(duì)象類(lèi)型中指定的 keys 變成必填的,你知道怎么實(shí)現(xiàn)么?知道答案的話,你喜歡以這種形式學(xué) TS 么?


網(wǎng)站欄目:同事看完這幾道題,發(fā)現(xiàn) TS 交叉類(lèi)型竟還沒(méi)入門(mén)!
瀏覽地址:http://www.dlmjj.cn/article/dpiepse.html