<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們可以使用 TypeScript 中的條件型別來根據邏輯定義某些型別,就像是在編寫程式碼那樣。
它採用的語法和我們在 JavaScript 中熟悉的三元運運算元很像:condition ? ifConditionTrue : ifConditionFalse。
我們來看看他是怎麼工作的。
假設我們有一個值,這個值可以表示使用者的出生日期或者年齡。
我們來定義這三種型別。
type Dob = string; type Age = number; type UserAgeInformation<T> = T extends number ? number : string;
Dob 和 Age 不需要多解釋,我們來解釋一下 UserAgeInformation。
它接受一個泛型,可以是任何型別。如果 T extends number 為 true,就意味著傳入的型別是 number 型別,我們就把 UserAgeInformation 設定為 number 型別。否則的話就設定為 string 型別。
我們在使用的時候可以這樣:
let userAge:UserAgeInformation<Age> = 100; let userDob:UserAgeInformation<Dob> = '12/12/1945';
除了上面介紹的用法,我們還可以通過檢查是否擴充套件了一個物件來更進一步。比如,假設我們的客戶有兩種型別:Horse 和 User。
兩種型別的客戶都有 age、name 兩個欄位。
我們來定義這幾種型別:
type User = { age: number, name: string, address: string } type Horse = { age: number, name: string } type UserAddress = { addressLine1: string, city: string, country: string, } type HorseAddress = { location: 'farm' | 'savanna' | 'field' | 'other' }
在未來,我們還可能會有其他型別的客戶,所以我們可以通過檢查 T 是否具有 address 屬性,如果有,我們使用 UserAddress 型別,否則使用 HorseAddress 型別。
type AddressComponents<T> = T extends { address: string } ? UserAddress : HorseAddress let userAddress:AddressComponents<User> = { addressLine1: "123 Fake Street", city: "Boston", country: "USA" } let horseAddress:AddressComponents<Horse> = { location: 'farm' }
T extends { address: string } 的含義是檢查 T 是否具有 address 屬性。
在三元表示式的條件返回中,我們也可以使用 T。
比如下面的例子:
type User = { age: number, name: string, address: string } type Horse = { age: number, name: string } type UserType<T> = T extends { address: string } ? T : Horse let myUser: UserType<User> = { age: 104, name: "John Doe", address: "123 Fake Street" }
T 被定義為 User,當我們呼叫 UserType 時,myUser 的型別就是 User,並且需要具有這種型別中所定義的欄位。
如果我們在這裡傳遞一個聯合型別:
type UserType<T> = T extends { address: string } ? T : string let myUser: UserType<User | Horse> = { age: 104, name: "John Doe", address: "123 Fake Street" }
myUser 的型別會變成是 User|string,因為 User 通過了條件檢測,但是 Horse 沒有通過,所以它的型別是字串。
如果我們以某種方式修改 T,比如把它設定為陣列。所有 T 的值都會被單獨修改。
type User = { age?: number, name: string, address?: string } type Horse = { age?: number, name: string } // 如果 T 包含型別是 string 的 name 屬性,就會返回 T[] type UserType<T> = T extends { name: string } ? T[] : never; // myUser 的型別是 User[]|Horse[],因為 User 和 Horse 都具有 name 屬性 let myUser:UserType<User | Horse> = [{ name: "John" }, { name: "Horse" }]
在這裡我們已經簡化了 User 和 Horse,它們只留下了必須需要的 name 欄位。在條件型別中,兩種型別都包含了 name。
所以兩者都會返回 true,並且返回的型別是 T[],由於兩者都返回 true,所以 myUser 的型別是 User[]|Horse[],所以我們可以簡單地提供一個包含 name 屬性的物件陣列。
這種行為通常很好,但是在某些情況下,我們希望返回一個陣列。
在這種情況下,如果我們想避免這樣分佈型別,可以在 周圍新增 { name: string }。
type User = { age?: number, name: string, address?: string } type Horse = { age?: number, name: string } // 我們避免分佈型別,因為 T 和 { name: string} 都在方括號中 type UserType<T> = [T] extends [{ name: string }] ? T[] : never; // 這樣現在的型別不同了,它是 (User|Horse)[] let myUser:UserType<User | Horse> = [{ name: "John" }, { name: "Horse" }]
通過使用方括號,我們的型別已經轉為 (User|Horse)[],而不是 User[]|Horse[]。
這在某些特殊的場景中很有用。但是條件型別會增加複雜性,不可以濫用。
我們也可以在使用條件時使用 infer 關鍵字。
假設我們有兩種型別,一種用於數位陣列,另一種用於字串陣列。
在這個例子中,infer 將會推斷陣列中每個專案的型別,並返回正確的型別:
type StringArray = string[] type NumberArray = number[] type MixedArray = number[] | string[] type ArrayType<T> = T extends Array<infer Item> ? Item: never // 因為 NumberArray 中專案的型別是 number,所以 myItem1 是 number 型別 let myItem1: ArrayType<NumberArray> = 45 // 因為 StringArray 中專案的型別是 string,所以 myItem2 是 string 型別 let myItem2: ArrayType<StringArray> = 'string' // 因為 MixedArray 中專案的型別是 number|string,所以 myItem3 是 number|string 型別 let myItem3: ArrayType<MixedArray> = 'string'
我們在條件型別中定義了一個新的引數 Item,它是 extends Array 中的子項 T。
但是我們必須傳入陣列,它才會有效,因為我們使用的是 Array。
如果 T 不是陣列,那麼 ArrayType 的型別將會是 never。
如果你剛接觸到 TypeScript 的條件型別,你可能會覺得很疑惑。但是它解決了某些特定情況下編寫型別比較複雜的一種解決方式。
如果你在某個專案中看到它,或者簡化你想你的專案程式碼,它或許很有用。
以上就是TypeScript 的條件型別使用詳解 的詳細內容,更多關於TypeScript 條件型別的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45