TypeScript常用类型速查手册
TypeScript常用类型速查手册
JavaScript是一个天生的弱类型语言,即变量申明的时候不需要指定类型,不同类型的变量之间也可以相互赋值。如果你已经习惯了这种写法,用起来也是挺爽的,因为不需要特意关心变量类型,直接写就行。但是这样做也很容易导致BUG,而且这些BUG基本都是运行时才出现,因为没有类型,静态检查是查不出问题的,只有运行时报错,可能直接一来就是个线上BUG。
TypeScript就是为JavaScript加上了类型检查,可以用静态检查排查出类型相关的问题,从而避免了线上的BUG。现在TypeScript已经很流行了,我们的新项目也引入了他,但是我用的不是很熟练,经常遇到不知道怎么定义类型的问题。所以我整理了这一份速查手册,从基本类型到interface,泛型这些都有,分享给大家~
基本类型
JavaScript的数据类型主要分为值类型和引用类型两大类。
值类型有string, number, boolean, undefined, 另外ES6引入了symbol, ES2020引入了bigint。这些类型都可以直接作为TS类型使用:
1 | let a: string = 'hello'; |
另外一大类是引用类型,主要是object和function,当然你可以将他们直接作为TS类型使用,但是我们不推荐这么做,object最好使用接口或者类来定义,而function最好给出详细的参数定义。我们先来个最简单的写法,后面单独看详细的推荐做法:
1 | let a: object = {}; |
一个变量可能有多个值的话,可以使用联合类型定义:
1 | let a: string | number | null = 123; |
上面这样申明一个变量是最常见的:
1 | let/const 名称: 类型 = 初始值; |
但是如果你有了初始值也可以不写类型,比如:
1 | let a = 'str'; // TS自动推导a是string类型 |
数组
长度不确定的数组
可以使用
T[]这种形式:1
let a: number[] = [1, 2, 3];
也可以使用
Array<T>这种形式:1
let a: Array<number> = [1, 2, 3];
长度确定的数组或者元素类型不一样的数组
可以使用元组[string, number]这种形式:
1 | let a: [string, number] = ['hello', 123]; |
不确定的类型
有时候我们确实会遇到类型不确定的情况,这时候我们可能会用到any,never,void, unknown。他们的主要作用和区别是:
any:放弃TS的类型检查和保护,可以是任意值,跟普通JS一样,一般不推荐使用这个:1
2
3let a: any = ['hello', 123];
a = 'hello';
a = 123;never:申明函数返回值,表示这个函数永远不会返回,一般用不到。因为一个函数你即使不写return也会默认返回undefined,永远不返回的是指无限循环之类,或者肯定抛出错误的:1
2
3
4
5
6
7let a: () => never = () => {
throw new Error();
}
let b: () => never = () => {
while (true) {}
}void: 表示函数没有返回值,其实就是默认返回undefined:1
2
3
4
5
6
7
8
9
10
11let a: () => void = () => {
let b = 1;
console.log(b);
}
let c: () => void = () => {
let b = 1;
console.log(b);
return undefined;
}unknown:安全的未知类型,在可以使用any的地方,推荐换成unknown,会有类型保护。具体来说就是unknown只能被赋值,而不能赋值给别人,而且不能直接使用,要想使用必须自己先做动态类型检测。比如下面这样直接用会报错:
1
2
3let a: (b: unknown) => void = (b) => {
let c:number = b + 1; // 报错:Object is of type 'unknown'.ts(2571)
}但是如果你使用前先检测一下就没问题:
1
2
3
4
5let a: (b: unknown) => void = (b) => {
if(typeof b === 'number') {
let c:number = b + 1;
}
}所以
unknown说直白点就是逼你在使用前先检测类型,自己保障类型安全。
函数
一般函数的定义是这样的:
1 | function intro(name: string, age: number): string { |
相较于普通的JS函数来说,只是给参数和返回值规定了类型而已。
函数是可以赋值给变量的,这个变量的类型应该是被赋值函数的签名,比如将上面的函数赋值给一个变量:
1 | const introFun: (name: string, age: number) => string = intro; |
这里的introFun的签名就是
1 | (name: string, age: number) => string |
这也是一个函数签名的标准格式:
1 | (参数1: 参数1类型, 参数2: 参数2类型 ...) => 返回值类型 |
这种函数变量我们也经常作为参数传递,比如另一个函数接收introFun作为参数,那可能就是这样的:
1 | function wrapper(place: string, introFun: (name: string, age: number) => string): string { |
这里的introFun的函数签名太长了,我们可以用type给他定义个别名:
1 | type TIntroFun = (name: string, age: number) => string; |
然后就可以用TIntroFun替换那个长长的签名了:
1 | function wrapper(place: string, introFun: TIntroFun): string { |
可选参数
上面那样写的函数参数都是必须要传的,不传就报错,但是有时候我们有些参数是可选的,可选参数需要在参数名字后面加?:
1 | function intro(name: string, age?: number): string { |
像age?: number这种可选参数,TS其实是自动联合了undefined类型,等价于age: string | undefined。
参数默认值
函数的参数是可以给默认值的,比如上面的name可以给一个默认值小飞:
1 | function intro(name: string = '小飞', age?: number): string { |
根据我们前面变量那里说的,一个变量有了初始值,其类型TS是可以自动推导的,所以name的类型可以省略,变成这样:
1 | function intro(name = '小飞', age?: number): string { |
但是可选参数不能给默认值,给了就会报错。
参数不确定
JS函数非常灵活,一个函数是可以支持不确定个数的参数的,比如这个加法函数:
1 | function add(...args) { |
这个函数接收任意多个数字,返回他们的和,这种函数类型怎么定义呢?args其实是一个数组,按照数组类型给他就行了:
1 | function add(...args: number[]): number { |
那如果参数的前面几个是确定的,剩余参数不确定怎么写呢?结合我们前面的函数参数类型和...args就行了:
1 | function add(name: string, ...args: number[]): string { |