TypeScript的高级类型简介

在前端开发中,大家入门ts其实是很简单的,只要掌握一些基本的类型知识就可以逐步的将js过渡到ts的应用,然而,当我们的项目很庞大复杂的时候,在开发过程中很容易将一些类型定义成any,这里主要介绍一下ts的高级类型,帮助大家更好的定义变量类型,从来减少any的使用。

泛型的介绍

泛型是强类型中比较重要的概念,使用泛型可以帮助我们提高代码的复用性,泛型是通过\color{DarkTurquoise}{<>}尖括号来表示的。尖括号中的字符被称作\color{DarkTurquoise}{类型变量},用来表示类型,接下来看一下概念中的描述:

泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型
示例:

 public testGenerics<T>(arg: T): T {   // T仅仅是个占位符,只不过大家都约定俗成的用T来占位
    return arg;
  }
  
  const str = this.testGenerics<string>('just test generics');

代码中的类型T,在没有调用testGenerics函数的时候是不确定的,只有在调用次方法之后,我们才能明确知道T代表的是什么类型,我们给他传入什么类型,他就给我们返回什么类型,这样数据就可以对应上了~

屏幕快照 2021-03-25 下午3.33.10.png

高级类型介绍

在实际开发中,大家可能比较常用一些基础类型,比如string、number、boolean等,但是当我们了解了一些高级类型后,我们可以定义更大复杂,更加灵活的接口类型。

1. 联合类型(|)

联合类型的规则和逻辑\color{DarkTurquoise}{“或”}是一致的,表示类型是连接多个类型中的任意一个

T | U

// demo
interface IPerson {
  age: number;
  gender: '女' | '男';
}

const person: Iperson = {
  age: 25;
  gender: '女'
}

2. 交叉类型(&)

交叉类型可以将多个类型合并成一个类型,写法和逻辑\color{DarkTurquoise}{“与”}相同

 T & U
 
 // demo 现在有两个类,我们可以通过交叉类型来实现一个新的属性的类型定义
 interface IPerson {
   age: number;
   gender: string;
 }

 interface IJob {
   title: string;
   years: number;
 }

 const life: IPerson & IJob = {
    age: 30,
    gender: 'nv',
    title: '开发',
    years: 10,
  };

3. 类型别名(type)

类型别名,它允许你为类型创建一个名字,这个名字就是类型的别名,从而你可以在多处使用这个别名,并且有必要的时候,你可以更改别名的值(类型),以达到一次替换,多处应用的效果,类型别名与声明变量的语法很类似,只需要把const,let换成type关键字即可。

type Alias = T | U
 
 // demo
 type sex =  '女' | '男';
 
 interface IPerson {
  age: number;
  gender: sex;
}

类型别名与接口的区别

  • 类型别名既可以表达接口所表达的类型,还比接口更加细粒度, 用起来更加随意
  • 接口interface可以被一个类class实现(implements),也可以使用extends来规范,但是类型别名是不行的
  • 类型别名可以与keyOf天然的结合使用

4. 类型索引(keyOf)

keyof 类似于 Object.keys ,用于获取一个接口中 Key 的联合类型

// demo
interface IPerson {
  age: number;
  gender: sex;
}

// 使用了keyOf后,只要IPerson修改了,type类型也会跟着自动修改

type personKeys = keyof IPerson;
//等价于
type personKeys = 'age' | 'gender';

5. 类型约束(extends

extends主要是用来对泛型加以约束的,他不像class使用extends是为了达到继承的目的。

 // demo
 type BaseType = string | number | boolean;
 
 public testGenerics<T extends BaseType>(arg: T): T {
   return arg;
 }
 
 this.testGenerics('123'); // 成功
 this.testGenerics({}); // 失败
屏幕快照 2021-03-25 下午4.48.16.png

extends的应用场景
extends 经常与 keyof 一起使用,例如我们有一个方法专门用来获取对象的值,但是这个对象并不确定,我们就可以使用 extends 和 keyof 进行约束,具体例子如下:

// 根据传入的obj来约束key的值
function getValue<T, K extends keyof T>(obj: T, key: K) {
  return obj[key]
}

6. 条件类型(U?X:Y)

条件类型的语法规则和三元表达式一致,一般用于一些类型不确定的情况

  T extends U ? X : Y // 如果T是U的子级 ,那么他的类型就是X,否则就是Y
  
  type Extract<T, U> = T extends U ? T : never; // 如果T是U的子级,那么返回T,否则抛弃

我们来看一下内置属性\color{DarkTurquoise}{Extract},他是用来提取公共属性的,接下来看一下实例:

 interface ITeacher {
  age: number;
  gender: sex;

}

interface IStudent {
  age: number;
  gender: sex;
  homeWork: string;
}

type CommonKeys = Extract<keyof ITeacher, keyof IStudent>; // "age" | "gender"
屏幕快照 2021-03-25 下午5.02.46.png

7. 类型映射(in)

in用来做类型映射,遍历已有接口的key或者遍历联合类型

type Test<T> = {
   [P in keyof T]: T[P];  
};
// keyof T  相当于 type ObjKeys = 'a' | 'b'
// P in ObjKeys 相当于执行了一次 forEach 的逻辑,遍历 'a' | 'b'

interface IObj {
  a: string;
  b: string;
}

type newObj = Test<IObj>;
屏幕快照 2021-03-25 下午5.07.40.png

工具泛型介绍

ts中还内置了许多工具泛型,接下来介绍一些常用的工具泛型

1. Partial

用于将一个接口的所有属性都设置成\color{DarkTurquoise}{可选状态},执行步骤就是先通过keyof T,取出类型变量T的所有属性,然后通过in进行循环,最后在每个属性上加上?

 type Partial<T> = {
    [P in keyof T]?: T[P]
 }
 
 // demo
 interface ITeacher {
  age: number;
  gender: sex;
}

const teacherA: Partial<ITeacher> = {age: 28};  // 此时用了Partial,即使不给gender赋值也不会报错

2. Required

Required的作用刚好与Partial相反,是将接口中的每个属性都改成\color{DarkTurquoise}{必须的},主要区别就是将Partial中的?替换成-?

type Required<T> = {
    [P in keyof T]-?: T[P]
}

3. Exclude

Exclude 的作用与上边介绍过的Extract刚好相反,如果 T 中的类型在 U 不存在,则返回,否则抛弃。

 type Exclude<T, U> = T extends U ? never : T
 
 //demo
 
 interface ITeacher {
  age: number;
  gender: sex;

}

interface IStudent {
  age: number;
  gender: sex;
  homeWork: string;
}

type ExcludeKeys = Exclude<keyof ITeacher, keyof IStudent>; // "homeWork"

4. Pick

Pick主要用于\color{DarkTurquoise}{提取接口中的某几个属性},我们可以通过这个泛型提取接口的属性,从而生成一个新的属性

type Pick<T, K extends keyof T> = {
    [P in K]: T[P]
}

// demo
interface IStudent {
  name: string
  age: number
  homework: string
}

type StudentA = Pick<IStudent, "name" | "age"> // 提取这个接口中的name和age属性

const zs: StudentA = {
  name: 'zs',
  age: 18
}

5. Omit

Omit 的作用刚好和 Pick 相反, 用来\color{DarkTurquoise}{排除接口中的某些属性}

type Omit<T, K extends keyof any> = Pick<
  T, Exclude<keyof T, K>
>

// demo
interface IStudent {
  name: string
  age: number
  homework: string
}

type StudentA = Omit<IStudent, "name"> // 排除掉这个接口中的name属性

const zs: StudentA = {
  age: 18,
  homework: '背诵课文'
}
屏幕快照 2021-03-25 下午5.37.43.png

总结

最近TypeScript发布了 4.0 的版本新增了很多功能,建议大家可以去更好的了解和掌握它,希望此篇文章可以帮助大家,让大家有所收获,减少甚至摆脱开发中的AnyScript~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容