TypeScript常用类型速查手册

TypeScript常用类型速查手册

JavaScript是一个天生的弱类型语言,即变量申明的时候不需要指定类型,不同类型的变量之间也可以相互赋值。如果你已经习惯了这种写法,用起来也是挺爽的,因为不需要特意关心变量类型,直接写就行。但是这样做也很容易导致BUG,而且这些BUG基本都是运行时才出现,因为没有类型,静态检查是查不出问题的,只有运行时报错,可能直接一来就是个线上BUG。

TypeScript就是为JavaScript加上了类型检查,可以用静态检查排查出类型相关的问题,从而避免了线上的BUG。现在TypeScript已经很流行了,我们的新项目也引入了他,但是我用的不是很熟练,经常遇到不知道怎么定义类型的问题。所以我整理了这一份速查手册,从基本类型到interface,泛型这些都有,分享给大家~

基本类型

JavaScript的数据类型主要分为值类型和引用类型两大类。

值类型有string, number, boolean, undefined, 另外ES6引入了symbol, ES2020引入了bigint。这些类型都可以直接作为TS类型使用:

1
2
3
4
5
6
7
let a: string = 'hello';
let b: number = 1234;
let c: boolean = true;
let d: undefined = undefined;
let e: symbol = Symbol('world');
let f: bigint = 1234567123456123n;
let g: null = null; // null也可以作为一个基本类型使用

另外一大类是引用类型,主要是objectfunction,当然你可以将他们直接作为TS类型使用,但是我们不推荐这么做,object最好使用接口或者类来定义,而function最好给出详细的参数定义。我们先来个最简单的写法,后面单独看详细的推荐做法:

1
2
let a: object = {};
let b: Function = () => {};

一个变量可能有多个值的话,可以使用联合类型定义:

1
2
3
let a: string | number | null = 123;
a = 'hello';
a = null;

上面这样申明一个变量是最常见的:

1
let/const 名称: 类型 = 初始值;

但是如果你有了初始值也可以不写类型,比如:

1
2
let a = 'str';    // TS自动推导a是string类型
a = 123; // 报错:因为number不能赋值给string类型

数组

长度不确定的数组

  1. 可以使用T[]这种形式:

    1
    let a: number[] = [1, 2, 3];
  2. 也可以使用Array<T>这种形式:

    1
    let a: Array<number> = [1, 2, 3];

长度确定的数组或者元素类型不一样的数组

可以使用元组[string, number]这种形式:

1
let a: [string, number] = ['hello', 123];

不确定的类型

有时候我们确实会遇到类型不确定的情况,这时候我们可能会用到anynevervoid, unknown。他们的主要作用和区别是:

  1. any:放弃TS的类型检查和保护,可以是任意值,跟普通JS一样,一般不推荐使用这个:

    1
    2
    3
    let a: any = ['hello', 123];
    a = 'hello';
    a = 123;
  2. never:申明函数返回值,表示这个函数永远不会返回,一般用不到。因为一个函数你即使不写return也会默认返回undefined,永远不返回的是指无限循环之类,或者肯定抛出错误的:

    1
    2
    3
    4
    5
    6
    7
    let a: () => never = () => {
    throw new Error();
    }

    let b: () => never = () => {
    while (true) {}
    }
  3. void: 表示函数没有返回值,其实就是默认返回undefined:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let a: () => void = () => {
    let b = 1;
    console.log(b);
    }

    let c: () => void = () => {
    let b = 1;
    console.log(b);

    return undefined;
    }
  4. unknown:安全的未知类型,在可以使用any的地方,推荐换成unknown,会有类型保护。具体来说就是unknown只能被赋值,而不能赋值给别人,而且不能直接使用,要想使用必须自己先做动态类型检测。

    比如下面这样直接用会报错:

    1
    2
    3
    let a: (b: unknown) => void = (b) => {
    let c:number = b + 1; // 报错:Object is of type 'unknown'.ts(2571)
    }

    但是如果你使用前先检测一下就没问题:

    1
    2
    3
    4
    5
    let a: (b: unknown) => void = (b) => {
    if(typeof b === 'number') {
    let c:number = b + 1;
    }
    }

    所以unknown说直白点就是逼你在使用前先检测类型,自己保障类型安全

函数

一般函数的定义是这样的:

1
2
3
function intro(name: string, age: number): string {
return `My name is ${name}, I am ${age} years old`;
}

相较于普通的JS函数来说,只是给参数和返回值规定了类型而已。

函数是可以赋值给变量的,这个变量的类型应该是被赋值函数的签名,比如将上面的函数赋值给一个变量:

1
const introFun: (name: string, age: number) => string = intro;

这里的introFun的签名就是

1
(name: string, age: number) => string

这也是一个函数签名的标准格式:

1
(参数1: 参数1类型, 参数2: 参数2类型 ...) => 返回值类型

这种函数变量我们也经常作为参数传递,比如另一个函数接收introFun作为参数,那可能就是这样的:

1
2
3
4
5
function wrapper(place: string, introFun: (name: string, age: number) => string): string {
console.log(`I am in ${place}`);

return introFun('Dennis', 18);
}

这里的introFun的函数签名太长了,我们可以用type给他定义个别名:

1
type TIntroFun = (name: string, age: number) => string;

然后就可以用TIntroFun替换那个长长的签名了:

1
2
3
4
5
function wrapper(place: string, introFun: TIntroFun): string {
console.log(`I am in ${place}`);

return introFun('Dennis', 18);
}

可选参数

上面那样写的函数参数都是必须要传的,不传就报错,但是有时候我们有些参数是可选的,可选参数需要在参数名字后面加?:

1
2
3
4
5
6
7
8
9
function intro(name: string, age?: number): string {
if (!age) {
return `My name is ${name}.`;
}

return `My name is ${name}, I am ${age} years old`;
}

intro('Dennis'); // age是可选的,可以不传

age?: number这种可选参数,TS其实是自动联合了undefined类型,等价于age: string | undefined

参数默认值

函数的参数是可以给默认值的,比如上面的name可以给一个默认值小飞

1
2
3
4
5
6
7
function intro(name: string = '小飞', age?: number): string {
if (!age) {
return `My name is ${name}.`;
}

return `My name is ${name}, I am ${age} years old`;
}

根据我们前面变量那里说的,一个变量有了初始值,其类型TS是可以自动推导的,所以name的类型可以省略,变成这样:

1
2
3
4
5
6
7
function intro(name = '小飞', age?: number): string {
if (!age) {
return `My name is ${name}.`;
}

return `My name is ${name}, I am ${age} years old`;
}

但是可选参数不能给默认值,给了就会报错

参数不确定

JS函数非常灵活,一个函数是可以支持不确定个数的参数的,比如这个加法函数:

1
2
3
4
5
function add(...args) {
return args.reduce((prev, item) => prev + item, 0);
}

console.log(add(1,2,3,4)); // 输出10

这个函数接收任意多个数字,返回他们的和,这种函数类型怎么定义呢?args其实是一个数组,按照数组类型给他就行了:

1
2
3
function add(...args: number[]): number {
return args.reduce((prev, item) => prev + item, 0);
}

那如果参数的前面几个是确定的,剩余参数不确定怎么写呢?结合我们前面的函数参数类型和...args就行了:

1
2
3
4
5
6
7
function add(name: string, ...args: number[]): string {
const total = args.reduce((prev, item) => prev + item, 0);

return `${name}: ${total}`;
}

console.log(add('Dennis', 1, 2, 3, 4, 5)); // 输出:Dennis: 15