类型系统
- 在开发过程中找错
- 使用”类型注解“来分析代码
- 仅存在于开发阶段
- 不会提供性能优化
类型
- 一个更方便我们去更简便地描述一个具有相应的属性和方法的值的东西
值
- 我们能够赋值给变量(variable)的东西
- 每一个值都会有相应的类型
类型的分类
-
元类型(primitive types)
- string、number、boolean、undefined、null、void、symbol
-
对象类型(Object types)
- function、arrays、classes、objects
-
基础类型:Boolean,Number,String,null,undefined 和 ES6的Symbol和ES10的BigInt
字符串类型
1 | //普通声明 |
数字类型
- 支持十六进制、十进制、八进制和二进制
1 | let notANumber: number = NaN;//Nan |
布尔类型
- 使用构造函数Boolean创造的对象不是布尔值
1 | let createdBoolean: boolean = new Boolean(1) |
- 事实上 new Boolean() 返回的是一个 Boolean 对象 需要改成
1 | let createdBoolean: Boolean = new Boolean(1) |
空值类型
- JavaScript 没有空值(Void)的概念,在 TypeScript 中,可以用
void
表示没有任何返回值的函数
1 | function voidFn(): void { |
-
void类型的用法,主要体现在我们不希望调用者关心函数返回值的情况下,比如通常的异步函数
-
void也可以定义undefined和null类型
1 | let u: void = undefined |
- 如果tsconfig.json 开启了严格模式,null 不能赋值给void
Null和undefined类型
1 | let u: undefined = undefined //定义undefined |
-
void 和 undefined 和 null 最大的区别
-
与void的区别是,undefined 和 null 是所以类型的子类型。也就是说undefined类型的变量,可以赋值给string类型的变量
1 | //这样写会报错 void 类型不可以分给其他类型 |
1 | //这样是没问题的 |
Any类型
- 没有强制限定哪种类型,随时切换类型都可以 我们可以对 any 进行任何操作,不需要检查类型
1 | let anys:any = 123 |
- 声明变量的时候没有指定任意类型默认为any
1 | let anys; |
- 弊端如果使用any 就失去了TS类型检测的作用
unkonw类型
- unknow类型比any更加严格当你要使用any 的时候可以尝试使用unknow
1 | //unknown 可以定义任何类型的值 |
1 | //如果是any类型在对象没有这个属性的时候还在获取是不会报错的 |
对象类型
- interface(接口)来定义一种约束
1 | //使用接口约束的时候不能多一个属性也不能少一个属性 |
1 | //重名interface 可以合并 |
1 | //继承 |
1 | //可选属性 使用?操作符 |
- 一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
1 | //任意属性[propName:string] |
1 | //只读属性readonly |
1 | //添加函数 |
数组类型
1 | //类型加中括号 |
1 | //最简单的方法是使用「类型 + 方括号」来表示数组: |
1 | //数组泛型 |
1 | //用接口表示数组 |
1 | //any 在数组中的应用 |
函数的类型
1 | //注意,参数不能多传,也不能少传 必须按照约定的类型来 |
1 | //通过?表示该参数为可选参数 |
1 | const fn = (name: string = "我是默认值"): string => { |
1 | //定义参数 num 和 num2 :后面定义返回值的类型 |
1 | const fn = (array:number[],...items:any[]):any[] => { |
1 | //函数重载 |
联合类型
1 | let myPhone: number | string = '010-820' |
1 | //函数使用联合类型 |
交叉类型
1 | //多种类型的集合,联合对象将具有所联合类型的所有成员 |
类型断言
值 as 类型 <类型>值
1 | interface A { |
1 | interface A { |
- 类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误
1 | (window as any).abc = 123 |
内置对象
1 | let b: Boolean = new Boolean(1) |
1 | let body: HTMLElement = document.body; |
class类
1 | class Person{ |
- 在TypeScript中是不允许直接在constructor中直接定义变量的,需要在constructor上面先声明
1 | class Person { |
- 这样引发了第二个问题,你如果定义了变量不用,也会报错,通常是给个默认值,或者是进行赋值
1 | class Person { |
- 类的修饰符
- public private protected
1 | class Person { |
使用public修饰符 可以让你所定义的变量,内部访问,也可以外部访问,如果不写默认就是public
使用private修饰符 代表定义的变量是私有的,只能在内部访问,不能在外部访问
使用protect修饰符 代表定义的变量是私有的,只能在内部和继承的子类中访问,不能在外部访问
static静态属性和静态方法
用static定义的属性,不可以通过this去访问,只能通过类名去调用
同理static静态函数,也不能通过this去调用,也只能通过类名去调用
如果两个函数都是static静态函数,可以通过this相互调用
- interface 定义类
1 | interface PersonClass { |
抽象类
1 | abstract class A { |
元组
- 如果需要一个固定大小的不同类型值的集合
- 元组就是数组的变种
- 元组(Tuple)就是固定数量的不同类型的元素的组合
- 元组与集合的不同之处在于,元组中的元素类型可以是不同的,而且数量固定,元组的好处在于可以把多个元素作为一个单元传递,如果一个方法需要返回多个值,可以把这多个值作为元组返回,而不需要创建额外的类来表示
1 | let arr:[number,string] = [1,'string'] |
1 | //应用场景 例如定义excel返回的数据 |
枚举类型
1 | enum Types{ |
增长枚举
1 | //定义了一个数字枚举, Red使用初始化为 1。 其余的成员会从 1开始自动增长 |
字符串枚举
1 | //在一个字符串枚举里,每个成员都必须用字符串字面量 |
异构枚举
1 | //枚举可以混合字符串和数字成员 |
接口枚举
1 | enum Types { |
const枚举
1 | //let 和 var 都是不允许的声明只能使用const |
反向映射
1 | //它包含了正向映射( name -> value)和反向映射( value -> name) |
类型推断
- 当变量声明和变量初始化在同一行的时候,类型推断系统才会起作用
- 手动添加类型注解的三种情况
1 | // 1)变量声明和变量初始化不在同一行 |