首页 > 技术文章 > typescript笔记-高级类型

beyonds 2020-08-24 18:11 原文

一、交叉类型(&): 将多个类型合拼在一起

 1 // 示例1
 2 type I0 = {TOP:"TOP"};//使用type声明的字面量类型
 3 interface I1 {
 4     name:string
 5     sleep:()=>void
 6 }
 7 interface I2 {
 8     name:string
 9     working:()=>void
10 }
11 
12 type I3 = I1&I2&I0
13 let O1:I3 = { //合拼的所有成员类型不能少也不能多
14     name:"121",
15     sleep(){},
16     working(){},
17     TOP:"TOP",
18 }
19 
20 // 示例2 
21 function Extend<T,U>(first:T,second:U):T&U{
22    let res = <T&U>{} ;//正确
23      // let res:T&U;//正确
24     //let res = {} as T&U; //正确
25    //  let res = {};// 没指定类型。报错
26     for (let key in first) {
27         (<any>res)[key] = first[key];//需要使用断言,否则报类型错误
28     }
29     for (let key in second) {
30         if (Object.prototype.hasOwnProperty.call(res, key)) {
31             (<any>res)[key] = second[key]
32         }
33     }
34     return res
35 }
36 let oj1 = {a:1}
37 let oj2 = {a:2,b:1}
38 let ro = Extend(oj1,oj2)

 

二、联合类型( | ):指定多个类型,多选一

 1 interface I1 {
 2     name:string
 3     sleep:()=>void
 4 }
 5 type I4 = I1|I2|'LEFT'|'TOP'|'RIGHT'|'BUTTOM'
 6 
 7 let O2:I4 = "BUTTOM" ;// 这里选了字面量类型 BUTTOM
 8 let O3:I4 = { // 这里选了I1 类型
 9     name:"ds",
10     sleep(){}
11 }

 

三、类型别名 type 

1. 只是给类型起一个名字,不会创建类型

2. 类型别名与接口区别,鼠标悬浮在类型上会显示字面量类型,而接口只会显示Interface

3. 类型别名不能别 extends和implements 

1 type T1=string  //原始类型
2 
3 type2 T2 = { // 对象类型
4    name:string,
5   age:number      
6 }
7 
8 type  T3 = "success" ||"fail" ;// 字面量类型

 

四、 获取值的类型 / 类型保护  typeof

 1 // 示例1:获取数据类型
 2 let O4 = {name:"lily",age:12}
 3 type I4 = typeof O4
 4 
 5 class O5 {
 6     uid:number|null=null
 7     constructor(){}
 8     getName(){}
 9     getAge(){}
10     
11 }
12 let obj = new O5()
13 type I6 = typeof obj
14 
15 // 示例2:做类型保护判断
16 function fn1(data:string|number){
17     if(typeof data==="string"){
18         // dosomething
19     }else if(typeof data==="number"){
20         // dosomething
21     }
22 }

 

五、 限制类型的属性选项 keyof

 1 //示例1
 2 type I1 ={
 3     id:number
 4     name:string
 5     age:number
 6 }
 7 type I2 =  keyof I1;// 获取到I1的类型属性key(是一个联合类型):id|name|age
 8 
 9 
10 //示例2:
11 // 原来写法
12 function getValue(obj:any,key:string){
13     return obj[key]
14 }
15 getValue({name:"limk"},"id");//如果获取的值不存在,不会有任何提示
16 
17 //限制类型写法
18 function getVlaueH<T>(obj:T,key:keyof T){
19     return obj[key]
20 }
21 getVlaueH({name:"mike"},"name");// 如果第二参数的key 不存在第一个参数的对象中就会报类型错

 

六、映射类型:keyof+in

 简单实现利用keyof+in 将可选类型变成必要类型

 1 type person = {
 2     name:string,
 3     age?:number,
 4     id:number
 5 }
 6 type Readolys<T>={
 7      [k in keyof T]-?:T[k]
 8 }
 9 let pser:Readolys<person> = {
10     name:"mike",
11     age:1,
12     id:1
13 }

 

七:条件类型:条件类型指由表达式所决定的类型

1 // 示例,常见写法
2 T  extends U?T:U ;// 如果T 类型 属于 U类型,则返回T 类型,否侧返回U类型
3 
4 示例:
5 let dataType = "TOP"|"LEFT"|"BUTTOM"|"RIGHT"
6 type Ttype<T,U> = T extends U?true:false
7 type res1 = Ttype<"TOP",dataType>;// true
8 type res2 = Ttype<"fail",dataType>;// false

 

八、 类型断言与保护

(1.)  当你确定知道某个值的类型,ts 可能在类型中检测不到,你就可以使用断言确定该值的类型

(2.) 官网说有两种写,一个是 as ,一个是尖括号<类型>值, 在typescript 中的tsx 只支持as 断言写法,还有一个 is 

 (8.1) as

//这里获取元素,ts会检测有可能不存在,你可以指定是它一定存在指定类型
let div = document.getElementById("div") as HTMLDivElement;//HTMLDivElement; 

   (8.2)  <类型>值:这里尖括号<> 不要和泛型搞乱了,泛型是在变量前<>; 断言是对值 重新声明类型,<>在值的前面

1  let str = "this is string";
2 let len = (<string>str).length

 (8.3)is :自定义类型保护, 一般在函数参数中用,用来判断某个属性属性某个类型

 1    //示例1
 2 function isString(s:unknown):s is string{
 3     return typeof s ==="string"
 4 }
 5 //示例2
 6  type Fish = {
 7      swim:()=>void
 8 }
 9 type Bird = {
10     fly:()=>void
11 }
12 function isFish<T>(pet: Fish | Bird): pet is Fish {
13     return (<Fish>pet).swim !== undefined;
14 }

 

九、通过索引访问类型的自类型

1 let I1 = {
2     id:1,
3     name:"name1",
4     childs:[
5         {id:2,name:"name2",childs:[]}
6     ]
7 }
8 type I2 = typeof  I1 
9 let O8:I2['childs'] = [{id:1,name:"like",childs:[]}]

 

推荐阅读