一、数据类型
1. ES6 中的9种数据类型
number(数字),boolean(布尔),string(字符串),undefined(未定义),null(空),symbol(符号),array(数组),function(函数),object(对象)。
2. TS 新增数据类型
void,any,never,元组,枚举,高级类型。
二、类型注解
TS 类型注解是一种静态类型检查机制,它用于在编写 TypeScript 代码时指定变量、函数参数、函数返回值、对象属性等的类型,以提高代码的可读性、可维护性和可靠性。
通过使用类型注解,我们可以在编译时捕获到一些类型错误,避免在运行时才发现类型错误,从而提高代码的质量和稳定性。
格式:
(变量/函数):类型名称
1. 基本类型
TS 支持 JavaScript 中的基本类型,如数字(number)、字符串(string)、布尔值(boolean)等,可以使用以下方式注解:
// 基本类型
let num: number = 1;
let bool: boolean = true;
let str: string = 'hello';
如果给一个变量赋值另一个变量,赋值的变量类型与这个变量的类型注解不一致,将会报错。如:
let str: string = 1;
报错:TS2322: Type 'number' is not assignable to type 'string'.,表示 number 类型不能赋值给 string 类型。
2. 数组
数组类型注解有两种方式,可以使用数组中元素的类型后面加上 "[]",也可以用泛型接口的方式。
// 数组类型
let arr: number[] = [1, 2, 3];
let arr1: Array<number> = [1, 2, 3];
arr: number[] 和 arr1: Array<number> 表示数组中的元素只能是 number 类型,如果有其它类型的元素,会报错:
let arr1: Array<number> = [1, 2, 3, 4];
报错:Type 'boolean' is not assignable to type 'number'.,表示 boolean 类型不能赋值给 number 类型。
如果我们想让一个数组中同时有多种类型的元素,那么可以使用联合类型:
let arr2: (number | string)[] = [1, 2, 3, 'hello'];
let arr3: Array<number | string> = [1, 2, 3, 4, 'hi'];
arr2: (number | string)[] 和 arr3: Array<number | string> 表示数组中的元素可以是 number 类型或者 string 类型。
3. 元组
元组类型注解指定了数组中每个元素的类型和数量。
// 元组类型
let tuple: [number, string] = [1, 'hello ts'];
tuple: [number, string] 表示这是一个元组,其中有两个元素,第一个元素类型为 number,第二个元素类型为 string。
如果元组中的元素个数和类型注解中声明的元素个数不匹配,会报错:
let tuple: [number, string] = [1, 'hello ts', 2];
报错:TS2322: Type '[number, string, number]' is not assignable to type '[number, string]'. Source has 3 element(s) but target allows only 2.,表示赋值源数组中有3个元素,但目标元组的类型注解中只声明了两个元素。
这里需要注意一个元组越界问题,如果我们用 js 中的数组方法改变元组的个数,是不报错的。但当我们访问数组中存在但元组注解中不存在的元素,会报错:
let tuple: [number, string] = [1, 'hello ts'];
tuple.push(2);
console.log(tuple); // [1,"hello ts",2]
console.log(tuple[2]); // 报错
报错:Tuple type '[number, string]' of length '2' has no element at index '2'.,表示你访问了元组中不存在的下标位置 2。
建议在开发过程中,不要改变元组中元素的个数。
4. 函数
如果我们在 TS 中定义一个函数:
let add = (x, y) => x + y;
会报错:TS7006: Parameter 'x' implicitly has an 'any' type. TS7006: Parameter 'y' implicitly has an 'any' type.,表示参数 x 和 y 的类型没有定义。这里就需要函数类型注解。
函数类型注解指定了函数的参数类型和返回值类型。
// 函数类型
let add = (x: number, y: number): number => x + y;
类型推断:我们指定了两个参数 x、y 的类型为 number,这里 TS 编辑器就可以推断出返回值的类型为 number。所以这里我们可以省略函数返回值的注解:
let add = (x: number, y: number) => x + y;
如果我们想使用 add = (x, y) => x + y 的这种经典方式定义函数,那我们就可以先定义函数的类型,然后再去定义函数。
// 定义函数的类型
let compiler: (x: number, y: number) => number;
compiler = (a, b) => a + b;
compiler:(x:number, y:number) => number 表示 compiler 是一个有2个 number 类型参数且返回值是 number 类型的函数。
5. 对象
看如下代码:
let obj: object = {x: 1, y: 2};
obj.x = 3;
我们定义了一个对象,有2个属性 x 和 y,然后修改 x 的值为3,会报错 TS2339: Property 'x' does not exist on type 'object'.,表示对象中没有 x 这个属性。报错的原因是我们定义了 obj 这个对象,但没有指定这个对象要包含哪些属性,这里就要用到对象类型注解。
对象类型注解指定了对象属性名和对应属性值的类型。
// 对象类型
let obj: { x: number, y: number } = {x: 1, y: 2};
obj.x = 3;
这里我们指定了 obj 是一个对象类型,有 x 和 y 两个 number 类型的属性,编译通过。
6. undefined 和 null
// undefined、null
let ud: undefined = undefined;
let nl: null = null;
在 TS中,undefined 和 null 是所有类型(包括 any 类型)的子类型,这意味着可以将 undefined 和 null 赋值给任何类型的变量。
但运行下面这段代码,可能会出现报错:
let n: number = 2;
n = undefined;
报错:TS2322: Type 'undefined' is not assignable to type 'number'.,表示 undefined 类型不能赋值给 number 类型。
这里我们需要打开 tsconfig.json 文件,将 strictNullChecks 的值改为 false。重启项目,会发现已经可以编译通过。
7. void
Void 类型注解指定了一个函数没有返回值。
// void
let func = () => {};
8. any
any 类型是 js 中变量的默认类型,any 类型注解可以指定变量的类型为任何类型。
// any
let x: any;
x = [];
x = {};
9. never
never类型表示永远没有返回值的类型。
// never
let error = () => {
throw new Error('error');
};
let enless = () => {
while (true) {}
};
一个函数在运行过程中抛出异常或出现死循环,那永远不会有返回值,返回值就是一个 never 类型。