一直想抽空来写写相关TS的东西,2022年了,TS现在已经成为咱们前端必备的基础技能,Vue3
已是Vue的
默认版本,而Vue3
就是使用TypeScript
来构建的,随着项目的不断更迭,包括我如今使用的nestjs
写后端,也是使用TS来支持的,更不用说React
和Vue
了。所以学习TS势在必行!
TypeScript
是一种由微软开发的自由和开源的变成语言,它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程–引用官方文档
TypeScript
不是JavaScript的替代品,而是会使JavaScript的步伐更加坚实遥远.TypeScript
提供最新的和不断发展的 JavaScript
特性.包括ES6
中的特性已经未来提案中的特性,比如装饰器(Decorators)
TypeScript | JavaScript |
---|---|
JavaScript 的超集用于解决大型项目的代码复杂性 | 一种脚本语言,用于创建动态网页 |
可以在编译期间发现并纠正错误 | 一种解释型语言,只能在运行时发现错误 |
强类型,支持静态和动态类型 | 弱类型语言 |
可以编译成指定版本的Javascript代码,不能直接在浏览器中运行,需要编译 | 可以直接在浏览器中使用 |
支持模块,泛型,和接口 | 不支持模块,泛型,和接口 |
定义变量的数据类型不能被改变 | 变量的数据可以改变,并赋予不同的数据类型 |
1.安装
npm install -g typescript
2.验证版本
tsc -v
tsc typescript.ts
typescript.ts => typescript.js
ts编译时,会将ts文件编译成js
文件
在
javascript
中,基础数据类型有:number
,string
,boolean
,null
,undefined
以及ES6
中的Symbol
和ES10
中的BigInt
//声明一个变量isFirst,并指定它的类型为boolean,赋值为true
let isFirst: boolean = true;
//ES5: var isFirst = true;
默认会编译成ES3
的版本,因为ES3
是一个比较老的版本,会考虑兼容性,兼容以前的运行环境
注意:在我们平时开发中,对于这种声明变量且赋值时,可以不用特定指定类型,因为在TS文件中,在声明变量且赋值时,会根据赋值来为变量指定相应的数据类型,所以上述一般可以直接简写:
xxx.ts
let isFirst = true //直接指定类型boolean
isFirst = 123 //编译时会直接报错
let num: number = 1;
let goodName: string = "Apple";
Symbol类型的值定义的是唯一且不可改变的,可用于作为标识符,或用于对象的属性名,可以保证不会出现同名的属性。
const sym = Symbol() //symbol被用做对象的key值时Symbol本身定义的是唯一且不可以改变的,需要使用const
const PersonObj = {
[sym]: 'liuqiao'
}
console.log(PersonObj[sym]) //liuqiao
在
Javascript
中没有空值(Void)的概念,在TS中可以用void
表示没有任何返回值的函数
function excute(): void {
console.log('start excute')
}
注意:声明void
类型的变量实际上没有什么意义,因为你只能将null
和undefined
赋值给它 (strictNullChecks
未指定时 )
let disable: void = undefined;
let enable: void = null;
let gname: void = 123;//报错
在TS中,
undefined
和null
,拥有各自本身的类型,分别是undefined
和null
let u: undefined = undefined;
let n: null = null;
和上述 void
相似,本身类型的用处不是很大
注意: 默认情况下,undefined
和null
是所有类型的子类型,也就是说你可以把undefined
和null
赋值给其他的基础类型
//------number--------
let num4: number = 10;
num4 = undefined;
num4 = null;
//------string--------
let gname: string = "Apple";
gname = undefined;
gname = null;
//------boolean--------
let isFoo: boolean = true;
isFoo = undefined;
isFoo = null;
在实际项目中,我们并不需要这样操作,为了保证严格的类型系统,我们一般会在工程文件(tsconfig.json
)指定"strictNullChecks":true
,此时undefined
和null
只能赋值给 void
和他们本身各自的类型。
有两种方式可以定义数组。第一种:类型+方括号表示法 第二种:Array<类型> 泛型语法
类型+方括号表示法
let goodList: string[] = ["Apple", "Banana", "Orange"];
//es5 => var goodList = ["Apple", "Banana", "Orange"]
Array<类型> 泛型语法
let goodList: Array<string> = ["Apple", "Banana", "Orange"];
//es5 => var goodList = ["Apple", "Banana", "Orange"]
元组类型表示一个已知数量和类型的数组,各元素的类型不必相同。比如定义一个数组,其中包含,string,number,boolean类型的值,这样称之为元组
let goodList: [string, number, boolean] = ["Apple", 5, true];
let goodList: [string, number, boolean] = [5, "Apple", 6];//ERROR,赋值必须与定义的类型一一对应
访问已知索引的元素
let goodList: [string, number, boolean] = ['Apple', 5, true]
console.log(typeof goodList[0], typeof goodList[1]) //string,number
元组支持解构赋值
let goodList: [string, number, boolean] = ['Apple', 5, true]
let [name, num, isExist] = goodList
console.log(`name: ${name}`) //name: Apple
console.log(`num: ${num}`) //num: 5
console.log(`isExist: ${isExist}`) //isExist: true
Enum
枚举类型用于取值被限定在一定范围内的场景,比如某状态:state(提交,审核,未审核,已通过)
enum StateEnum {
PADDING, // 申请中
PASS, // 已完成
ABORT // 驳回
}
默认情况下:PADDING 的初始值为0,其他成员会自增长跟着+1,当然,我们也可以设置 PADDING 的初始值, 其他成员不想+1,也可以设置手动指定特定的值
enum StateEnum {
PADDING = 1, // 申请中
PASS, // 已完成
ABORT // 驳回
}
enum StateEnum {
PADDING = 1, // 申请中
PASS = 3, // 已完成
ABORT = 5 // 驳回
}
注意:数字枚举是支持反向映射的,比如我要通过枚举中的值来取枚举的属性,可以这样做
console.log(StateEnum.PADDING) //0
console.log(StateEnum[0]) // PADDING
数字枚举,还支持成员中有计算成员
enum StateEnum {
PADDING, // 申请中
PASS = PADDING + 5, // 已完成
ABORT, // 驳回
}
enum StateEnum {
ABORT = 'abort', // 撤回
REVIEW = 'review', // 审核
EDIT = 'edit', // 编辑
SUBMIT = 'submit' // 提交
}
异构枚举的成员是数字和字符串的混合
enum StateEnum {
PADDING, // 申请中
PASS, // 已完成
ABORT, // 驳回
REVIEW = 'review', // 审核
EDIT = 'edit', // 编辑
SUBMIT = 'submit' // 提交
}
常量枚举是一种比较特殊的枚举
const
关键字来修饰的枚举JavaScript
代码,在使用其成员时,会被内联进来const enum StateEnum {
PADDING, // 申请中
PASS, // 已完成
ABORT, // 驳回
}
let padding = StateEnum.PADDING;
上面说了,通过const
定义的常量枚举类型,编译阶段会删除的,上面这段会编译成下面这样:
//编译后的代码:
var padding = 0 /* PADDING */;
任意类型,声明为any的变量可以被赋予任意类型的值,any类型是类型系统的顶级类型
let gname: any = 123;
gname = "123";
gname = true;
gname = [];
gname = {};
gname = null;
gname = undefined;
//any类型的值也可以赋给任何类型
let number: string = gname;
let isDone: boolean = gname;
let arrayList: [] = gname;
TS允许对any
类型的值,做任何操作,可以为any
类型的变量赋予任意类型的值,也可以让任何类型赋予给any
类型。这样也就意味着,使用any
类型,也就放弃了TS提供的类型保护机制。所以在TS中,一般不建议使用any
类型
注意一点:
变量如果在声明的时候,未指定其类型,那么它会被识别为any类型(隐式的any)
let gname;//未指定类型,会被默认为any类型
gname = 123;
gname = "123";
gname = true;
表示未知类型的值,可以被认为是:
类型安全的any
和any
类型一样,所有类型都可以赋值给unknow
let gname: unknown = 123;
gname = "123";
gname = true;
gname = [];
gname = {};
gname = null;
gname = undefined;
但是和any类型不同的是,当我们把unknow
类型赋值给其他类型时:
let gname: unknown = 123;
let price: unknown = gname; //不会报错,正常编译
let remark: any = gname; //不会报错,正常编译
let number: string = gname; //报错
let isDone: boolean = gname; //报错
let arrayList: [] = gname; //报错
所以:unknow
类型只能被赋值给any
类型和unknow
类型本身,正因为这个特性,被认为是类型安全的any
结论:
unknow
与any
的最大区别是:任何类型的值可以赋值给any
,any
类型的值可以赋给任何类型,unknow
类型是任何类型的值可以赋值给它,但是它只能赋值给unknow
和any
在javascript
中,Object
是一个构造函数,一切皆对象,而object
是没有的,但是在TypeScript2.2
的版本中,加入了object
,用于表示所有的非原始类型
Object: 首字母大写,大Object
object: 首字母小写,小object
{ } : 空对象
表示所有的非原始值类型。包括对象,函数,数组,正则等,还有其他
javascript
中的一些内置对象.
let user: object;
user = [1, "2", 3];//正常
user = function () {};//正常
user = {};//正常
user = null;//严格模式下,会编译不通过
user = undefined;//严格模式下,会编译不通过
//报错
user = 1;
user = "1";
user = false;
object
表示着所有非原始类型,也就是说,不能把原始类型等值(string,number,boolean,bigint,symbol
)赋给object
,虽然null和undefined
也是原始类型,但是在非严格模式下,undefined和null
可以赋值给object
的
Object是一个对象,包含所有对象类型。
let user: Object;
user = [1, "2", 3];
user = function () {};
user = {};
user = null;
user = undefined;
user = 1;
user = "1";
user = false;
//都是可以编译正常的
let stuinfo: object;
user = stuinfo;//正常
以上代码都是可以编译正常的,但是严格模式下,null和undefined是不能赋给Object的
空类型:{ } 表示一个没有成员的对象
let user = {};
let userinfo: {};
两种声明方式都是可以的。
let user = {};
user = 2;
user = "2";
user = false;
user = [1, "2"];
user = function () {};
user = null;
user = undefined;
//都是可以编译正常的
空对象类型和Object
一样,类型值都是可以为原始类型的,严格模式下,null和undefined是不能赋给{}的
共通点: object,Object,{ } 都是可以定义对象类型的,并且严格模式下,不能被赋值为null和undefined
Object和object:
Object和{ }
object和{ }
PS: 以上只是初步介绍了下对象相关的概念,其中很多细节,没有都展出,后面深入TS后,再慢慢列举出来
never
类型表示永远不会存在的值的类型
目前只有2种情况
在函数体中,抛出异常
在函数体中,死循环
//抛出异常
function error(msg: string): never {
throw new Error(msg);
}
//死循环
function loop(): never {
while (true) {
}
}