12.TypeScript完全解读-高级类型(1)
高级类型中文网的地址:https://typescript.bootcss.com/advanced-types.html
创建新的测试文件
index.ts内引入
交叉类型
交叉类型就是取多个类型的并集
Object.assign就是合并两个对象,包含两个对象各有的属性,合成一个总的对象
定义的函数也是接收两个对象,最后返回两个对象合并后的结果。
返回值里既包含arg1,也包含了arg2的属性
所以返回的类型就可以用交叉类型来返回: T & U
res是个数组所以这里返回res肯定是不对的。
这里需要使用类型断言
调用这个方法传进去两个对象,最终返回的是两个对象合并后的对象,所以这里再通过点.就可以把a和b这两个属性都点出来了
这就是交叉类型,可以理解为与的一个操作
联合类型
这样就表示当前这个类型几课时type1也可以是type2还可以是type3,只要是其中的一种就可以
这里先判断是否是string类型,如果是stirng类型就返回它的length,如果不是string类型,就先tostring 一下然后再返回它的的length
那么这里既可以是stirng类型,也可以是number类型
传入布尔类型那么就会报错了。这就是联合类型
类型保护
ts在编译阶段就会帮我们监察错误,有些数据只有在代码运行之后才能知道结果
Math.random()是0到1的随机数,乘以10就是0到10的
item的值是随即的不固定的,这个值在编译阶段是无法确定是哪个类型的值的
所以有时候就需要先判断他的类型
这里判断item的length,length属性是stirng类型才有的,如果是string类型就返回它的length,如果是number类型那么就返回它的toFixed方法。但是这里报错了
报的错误
我们选中getRandomValue方法代码块。看到它返回的是一个stirng或者number的联合类型。
这里的itme也是stirng或者是number类型,这段逻辑在js是没有问题的 但是在ts中是有问题的,它会监测item的类型,
所以这个时候我们就要用到类型保护
如果不用类型保护的话,也可以使用类型断言,这个地方有个缺点,就是多个地方只要用到这个item的地方就要使用类型断言
所以我们可以使用类型保护
返回值的类型是value is string。看上去像是一句话。用is表示返回值的类型
把鼠标放到item上看一下,这里已经判断出了这是一个stirng类型。就是通过类型保护ts知道了item是一个stirng类型,那么if代码块里面的item都是一个stirng类型
既然你的值要么是numer要么是string类型,if是string类型了。 那么else里面自动判断出是number类型的.这个要比类型断言使用起来方便多了。但是上面多定义了一个函数
函数里面我们就定义了一个判断,是不用定义一个函数这么复杂的,定义函数去判断适合逻辑比较复杂的类型的判断
这里简单的类型判断,我们可以使用第二种方式typeof
typeof在js里面是有这个关键词的,可以判断值的类型
在ts中 会把typeof item当做一个类型保护。但是这个类型保护只能登过这种 === 等号或者!== 不等于这种形式来定义来比较。
在js中可以用includes判断一个字符串或者数组里面是否包含某个指定的东西
typeof 在ts中只能做等或者不等的操作不会把这段include的识别为类型保护的,后面的逻辑也不会判断出item是什么类型的
typeof后面要比较的类型,必须这四种的一种:string、number、boolean、symbol
valueList这里我们修改一下
item的类型就是一个空的对象
这里用typeof判断object类型
所以后面的判断不会准确的判断
你可以这么写,但是不会被识别为类型保护
instanceof类型保护
instanceof也是js中的原生操作符,判断一个实例是不是某个构造函数创建的实例。或者是不是使用es6语法的某个类创建的
在ts中使用instanceof同样具有类型保护的效果
getRandomItem随机数,如果小于0.5就创建class1的实例,如果不是 就创建class2的实例
使用instanceof类型保护,
null和undefined
是任何类型的子类型
这里定义values默认是123会自动推断出来是string类型
但是其实这里的类型默认情况下相当于是一个strng | undefined的联合类型
values给他赋值一个undefined也是可以的。就是上面上面定义的时候相当于string和undefined的联合类型了。所以在ts中有严格模式
ts.config内有严格模式可以打开,默认是关闭的。这里打开这个选项
打开之后,把undefined赋值给values就会报错了。values是stirng类型,这里就不能再把undefined赋值给values了
ts会将null和undefined区别对待,这和js里也是一致的
下面 这三种是完全不同的类型
当开启了ts的属性strickNullChecks设置为true了
可选参数会被自动加上undefined,成为一个联合类型。ts会自动做这么一个处理
可选属性也是会被加上undefined的 这里不在举例
修改了tsconfig.json以后,一定要把项目停掉,重新编译项目npm start
类型保护和类型断言
当我们的参数或者属性类型是联合类型或者any类型这种不唯一的类型时,我们就可能需要使用类型保护来做一些类型的判断
定义函数,函数的返回值类型是number
精简代码。如果value是null这里使用 || 会隐式转换成false,false的话就会走后面的 空字符串的逻辑,
当value是null的时候,就会整体返回那个空字符串,然后空字符串再取length的值那么就是0
这里用了一个嵌套函数,里面又套了一个函数getRes()
如果num是null就会隐式转换为false 就会取0.1,如果num不为null那么就默认返回num的值
这里报错了,num可能为null,当num为null 的时候就不能调用toFixed方法了。因为有嵌套函数,编译器是无法去除嵌套函数的null的
所以这里我们就要使用类型断言,用叹号在不为null的值的后面。
在num的值的后面加叹号
先取整,再toString
类型别名
就是给一种累心起一个别的名字,之后只要使用这个类型的时候,都可以用这个新的名字,作为类型的代替。
只要你想指定类型是stirng的地方,都可以使用TypeString来指定
例如这里,我原本是要指定str2是string类型
现在我就可以全完用TypeString来代替
类型别名也可以使用泛型,这里用type会报错,需要tsconfig设置interface-over-type-literal:false才可以。要不然这里只能用interface接口
设置为false:interface-over-type-literal:false。自己开发项目还是建议开启。
使用类型别名的时候,也可以在属性引用自己
child属性用了他自己本身,其实就是定义了一种树状的结构
一层一层的嵌套下去
只可以在对象属性中引用类型别名自己。不能直接使用自己。下面这种就会报错了
类型别名只是为其他类型起了新的别名来引用这个类型,所以当它为接口起别名时不能使用extends和implements
接口和类型别名有时 是起到一样的作用的
下面先定义一个类型别名,在定义一个接口,里面都只有属性num属性为number类型,在定义_alias我可以指定类型是Alias类型别名
同时也可以指定_alias指定为接口类型达到了同样的效果
接口的实例赋值给类型别名的实例,这里是可以的 没有报错
什么时候用类型别名,什么时候使用接口?
刚才的例子我们使用类型别名会自动转为接口,tsconfig.json内这里设置为false了才可以使用的类型别名
当你定义的类型要用于扩展要用implements来修饰的时候用接口。当无法通过接口,并且需要使用联合类型或者元祖类型的时候用类型别名
自变量类型
自变量包含字符串自变量和数字自变量两种
通过type制定Name是字符串自变量类型
制定name3类型为Name,Name是Lison这个字符串的字符串自变量。所以我给name3赋值Lison这个字符串是没问题的
如果给赋一个别的值
还可以使用联合类型来使用多个字符串。
Direction就是后面四个字符串的字符串自变量构成的一个联合类型
返回传的参数的首字母
在调用方法的时候,这里就列出来了智能选择这四个作为参数
传值哈哈就会报错了
数字自变量
定义数字自变量Age为18.
再定义一个接口,里面的属性age是自变量类型Age ,其实就是规定了智能是18
那么在_info继承了接口后,age的值必须是18如果不是就会报错了
枚举成员类型
能够做类型使用的枚举要符合三个条件
1.不带初始值的枚举成员
2.成员的值为字符串自变量。
3.值是数值自变量或者带有一个负号的数值自变量
以上三种满足一个就可以。那么这个枚举值和他的枚举成员都可以做为类型来使用
可辨识联合类型
可以把单例类型,联合类型、类型保护、类型别名,这几种类型合并,创建一个可辨识联合的高级类型,也可以成为标签联合或者代数数据类型
可辨识联合要求具有两个要素
1.具有普通的单例类型属性
2.一个类型别名包含了哪些类型的联合(也就是把几个类型封装为联合类型并且起个别名)
shapes是三个接口的联合
在写代码的时候,当判断了是什么类型,自动把接口内的属性自动提示出来了
三个接口内都有特征,kind并且值都不一样,所以用kind来做特征
shape别名包含了三个接口的联合
定义函数的时候制定类型就是shape这个联合类型。在写switch的时候,通过编译s.kind这个可辨识的特征。我们在写下面的代码时候,ts已经帮我们判断出了每个分支的条件都可以为(二声)什么
当我们case判断是square,他会判断s就是Square这个接口的类型,会把你可以访问的属性给你列出来。这就是一个可以辨识的联合
幂运算,一个星号是乘以,两个星号就是幂运算。这就是圆的半径的平方。幂运算我听着视频说的不是很清楚,可能是ES7的语法
一共三种类型,这里如果漏了 希望编译器给予提示
就要用到下一个知识点。什么什么检查。
两种检查方式,
先确定这个属性是否是true,打开的
指定返回类型,如果遗漏了就会报错
如果没有开tsconfig.json内的strictNullCheck。这里的返回值类型可以设置为undefined.编译器会自动认为这里返回值类型是个联合类型number或者undefined
既然开了strictNullCheck已经设置为true了,就是打开了。这里的分支没有任何一条执行,就会返回undefined。undefined和number是不能赋值的。所以这里我就知道少了一个分支。
这种方法比较简单,但是对旧的代码支持不好。因为以前没有strictNullCheck这个选项
第二种方法:
当一个函数返回错误,坐着不可能有返回值类型的时候,返回值的类型为never,所以我们可以给switch添加一个default
先把这个注释掉
关掉后,这里就不报错了
需要定义一个额外的函数,接收参数是never类型,返回值类型也是never。然后在switch里面加一个default的分支。
如果缺少了一个项,就会走定义的函数assertNevert函数,就会提示报错 。
不仅在编译器提示我们错误运行的时候也会报错。