目录
TypeScript 的条件类型使用方式条件类型和 keyof 组合在条件返回中使用 T在类型输出中使用 T 时的联合类型使用条件类型推断类型总结TypeScript 的条件类型使用方式
我们可以使用 TypeScript 中的条件类型来根据逻辑定义某些类型,就像是在编写代码那样。
它采用的语法和我们在 JavaScript 中熟悉的三元运算符很像:condition ? ifConditionTrue : ifConditionFalse。
我们来看看他是怎么工作的。
(资料图片仅供参考)
假设我们有一个值,这个值可以表示用户的出生日期或者年龄。
如果是出生日期,那他的类型应该是 string。如果是年龄,那他的类型是 number。我们来定义这三种类型。
type Dob = string; type Age = number; type UserAgeInformation= T extends number ? number : string;
Dob 和 Age 不需要多解释,我们来解释一下 UserAgeInformation。
它接受一个泛型,可以是任何类型。如果 T extends number 为 true,就意味着传入的类型是 number 类型,我们就把 UserAgeInformation 设置为 number 类型。否则的话就设置为 string 类型。
我们在使用的时候可以这样:
let userAge:UserAgeInformation= 100; let userDob:UserAgeInformation = "12/12/1945";
条件类型和 keyof 组合
除了上面介绍的用法,我们还可以通过检查是否扩展了一个对象来更进一步。比如,假设我们的客户有两种类型:Horse 和 User。
两种类型的客户都有 age、name 两个字段。
User 类型的客户还有一个 address 字段,它表示了详细的地址。Horse 类型的客户有 location 两个字段,它只是表示一个大概的位置。我们来定义这几种类型:
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 extends { address: string } ? UserAddress : HorseAddress let userAddress:AddressComponents = { addressLine1: "123 Fake Street", city: "Boston", country: "USA" } let horseAddress:AddressComponents = { location: "farm" }
T extends { address: string } 的含义是检查 T 是否具有 address 属性。
在条件返回中使用 T
在三元表达式的条件返回中,我们也可以使用 T。
比如下面的例子:
type User = { age: number, name: string, address: string } type Horse = { age: number, name: string } type UserType= T extends { address: string } ? T : Horse let myUser: UserType = { age: 104, name: "John Doe", address: "123 Fake Street" }
T 被定义为 User,当我们调用 UserType 时,myUser 的类型就是 User,并且需要具有这种类型中所定义的字段。
在类型输出中使用 T 时的联合类型
如果我们在这里传递一个联合类型:
type UserType= T extends { address: string } ? T : string let myUser: UserType = { 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 extends { name: string } ? T[] : never; // myUser 的类型是 User[]|Horse[],因为 User 和 Horse 都具有 name 属性 let myUser:UserType = [{ 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] extends [{ name: string }] ? T[] : never; // 这样现在的类型不同了,它是 (User|Horse)[] let myUser:UserType = [{ name: "John" }, { name: "Horse" }]
通过使用方括号,我们的类型已经转为 (User|Horse)[],而不是 User[]|Horse[]。
这在某些特殊的场景中很有用。但是条件类型会增加复杂性,不可以滥用。
使用条件类型推断类型
我们也可以在使用条件时使用 infer 关键字。
假设我们有两种类型,一种用于数字数组,另一种用于字符串数组。
在这个例子中,infer 将会推断数组中每个项目的类型,并返回正确的类型:
type StringArray = string[] type NumberArray = number[] type MixedArray = number[] | string[] type ArrayType= T extends Array ? Item: never // 因为 NumberArray 中项目的类型是 number,所以 myItem1 是 number 类型 let myItem1: ArrayType = 45 // 因为 StringArray 中项目的类型是 string,所以 myItem2 是 string 类型 let myItem2: ArrayType = "string" // 因为 MixedArray 中项目的类型是 number|string,所以 myItem3 是 number|string 类型 let myItem3: ArrayType = "string"
我们在条件类型中定义了一个新的参数 Item,它是 extends Array 中的子项 T。
但是我们必须传入数组,它才会有效,因为我们使用的是 Array。
如果 T 不是数组,那么 ArrayType 的类型将会是 never。
总结
如果你刚接触到 TypeScript 的条件类型,你可能会觉得很疑惑。但是它解决了某些特定情况下编写类型比较复杂的一种解决方式。
如果你在某个项目中看到它,或者简化你想你的项目代码,它或许很有用。
以上就是TypeScript 的条件类型使用详解 的详细内容,更多关于TypeScript 条件类型的资料请关注脚本之家其它相关文章!
X 关闭
X 关闭
- 1联想拯救者Y70发布最新预告:售价2970元起 迄今最便宜的骁龙8+旗舰
- 2亚马逊开始大规模推广掌纹支付技术 顾客可使用“挥手付”结账
- 3现代和起亚上半年出口20万辆新能源汽车同比增长30.6%
- 4如何让居民5分钟使用到各种设施?沙特“线性城市”来了
- 5AMD实现连续8个季度的增长 季度营收首次突破60亿美元利润更是翻倍
- 6转转集团发布2022年二季度手机行情报告:二手市场“飘香”
- 7充电宝100Wh等于多少毫安?铁路旅客禁止、限制携带和托运物品目录
- 8好消息!京东与腾讯续签三年战略合作协议 加强技术创新与供应链服务
- 9名创优品拟通过香港IPO全球发售4100万股 全球发售所得款项有什么用处?
- 10亚马逊云科技成立量子网络中心致力解决量子计算领域的挑战