TypeScript 的条件类型使用示例详解_JavaScript

来源:脚本之家  责任编辑:小易  
目录
TypeScript 的条件类型使用方式条件类型和 keyof 组合在条件返回中使用 T在类型输出中使用 T 时的联合类型使用条件类型推断类型总结

TypeScript 的条件类型使用方式

我们可以使用 TypeScript 中的条件类型来根据逻辑定义某些类型,就像是在编写代码那样。

它采用的语法和我们在 JavaScript 中熟悉的三元运算符很像:condition ? ifConditionTrue : ifConditionFalse。

我们来看看他是怎么工作的。

假设我们有一个值,这个值可以表示用户的出生日期或者年龄。

如果是出生日期,那他的类型应该是 string。如果是年龄,那他的类型是 number。

我们来定义这三种类型。

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';

条件类型和 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> = 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

在三元表达式的条件返回中,我们也可以使用 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,并且需要具有这种类型中所定义的字段。

在类型输出中使用 T 时的联合类型

如果我们在这里传递一个联合类型:

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 条件类型的资料请关注真格学网其它相关文章!

您可能感兴趣的文章:TypeScript中条件类型精读与实践记录深入了解TypeScript中的映射类型直观详细的typescript隐式类型转换图文详解typescript返回值类型和参数类型的具体使用详解TypeScript使用及类型声明文件Typescript类型系统FLOW静态检查基本规范

  • 本文相关:
  • google 地图api map()构造器详解
  • 用 或 || 来兼容firefox
  • 微信小程序 侧滑删除(左滑删除)
  • 微信小程序(十六)form组件详细介绍
  • js前端使用canvas编写一个签名板
  • 微信小程序 swiper组件详解及实例代码
  • js轻量级函数式编程实现xdm三
  • 微信小程序 密码输入(源码下载)
  • 微信小程序 toast组件详细介绍
  • 微信小程序 基础知识css样式media标签
  • 正则表达式 获取 <script type="text/javascript">XXXXX</script>
  • 修改个代码<script type="text/javascript"> document.write('<scri...
  • <script type="text/javascript" src="./js/jquery-1.4.2.js"></script>
  • <script type='text/javascript'>
  • html(不是jsp)页面中 <script type = "" src = "" />怎么获...
  • <script type="text/javascript"> </script> 和 <script></...
  • <script type="text/javascript"> </script> 和 <script></...
  • <script type ="text/javascript">aaa</script> 怎么用正则...
  • 如何评价TypeScript接口的扩展,自动混合的特性
  • <script type="text/javascript"> window.onload=function(){ ...
  • 一个程序中可以有几个<script type="text/javascript"> </...
  • <script type="text/javascript" > var total=0;total=Number(2.1)+N...
  • 如何在TypeScript中应用像Jquery之类的第三方JavaScript框架
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全javascriptasp.netphp编程ajax相关正则表达式asp编程jsp编程编程10000问css/htmlflex脚本加解密web2.0xml/rss网页编辑器相关技巧安全相关网页播放器其它综合dart首页javascripttypescript中条件类型精读与实践记录深入了解typescript中的映射类型直观详细的typescript隐式类型转换图文详解typescript返回值类型和参数类型的具体使用详解typescript使用及类型声明文件typescript类型系统flow静态检查基本规范google 地图api map()构造器详解用 或 || 来兼容firefox微信小程序 侧滑删除(左滑删除)微信小程序(十六)form组件详细介绍js前端使用canvas编写一个签名板微信小程序 swiper组件详解及实例代码js轻量级函数式编程实现xdm三微信小程序 密码输入(源码下载)微信小程序 toast组件详细介绍微信小程序 基础知识css样式media标签微信小程序 数组(增,删,改,查)等操作实例详解微信小程序 for 循环详解微信小程序 小程序制作及动画(animation样式)详解微信小程序 input输入框控件详解及实例(多种示例)微信小程序 input输入框详解及简单实例微信小程序 传值取值的几种方法总结微信小程序 时间格式化(util.formattime(ne微信小程序中使元素占满整个屏幕高度实现方法微信小程序 wx.request(接口调用方式)详解及实例微信小程序通过api接口将json数据展现到小程序示例微信小程序开发之相册选择和拍照详解及实例代码javascript?api?resizeobserver使用示例微信小程序实现页面跳转传值的方法利用js实现简单开关灯代码js微前端microapp基础使用typescript基础类型介绍微信小程序上滑加载下拉刷新(onscrolllower)分批加载数据(一)非常好的js代码微信小程序实现缓存根据不同的id来进行设置和读取缓存微信小程序 wxapp视图容器 view详解
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved