TypeScript完全解读(26课时)_12.TypeScript完全解读-高级类型(1)

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函数,就会提示报错 。

不仅在编译器提示我们错误运行的时候也会报错。

原文地址:https://www.cnblogs.com/wangjunwei/p/10859537.html