为什么选择使用 Typescript
Typescript 是 JavaScript 的超集,是一种静态类型语言,能够限制变量的数据类型,方便调试和代码理解,适用于大型项目。
any 与 unknown 与 never
any
- any 类型是 TypeScript 最宽松的类型,任何类型都可以赋值给 any 类型的变量
- 变量类型一旦设为 any,这个变量就不再有类型检查
- any 类型的变量也可以复制给任意类型的其他变量,造成类型污染
unknown
- unknown 类型是 TypeScript 最严格的的类型,任何类型都可以赋值给 unknown 类型的变量
- unknown 需要先进行类型检查,然后才能执行操作
- unknown 类型是 any 类型的安全替代,保留了类型检查
never
- never 类型是 TypeScript 类型系统中的底类型,任何类型都可以赋值给 never 类型,但不能反过来
- never 类型表示不可能存在的值,变量被赋予 never 类型后,不能再进行操作
类型系统
基本类型
- TypeScript 的 8 中基本类型:boolean、string、number、bigint、symbol、object、undefined、null,类型都必须小写
- bigint 与 number 不兼容,且如果使用 bigint,编译 target 不能低于 es2020
- object 类型包含所有的对象、数组和函数,属于复合类型
- undefine、null 是两种特殊类型,既表示类型,也表示各自唯一的值
包装对象类型
- Boolean、String、Number、Bigint、Symbol 为包装对象类型,既表示字面量,又表示包装对象;boolean、string、number、bigint、symbol 只能表示字面量类型。
const s1:String = 'hello'; // 正确
const s2:String = new String('hello'); // 正确
const s3:string = 'hello'; // 正确
const s4:string = new String('hello'); // 报错
- TypeScript 很多内置方法只支持 boolean、string、number、bigint、symbol 这些小写,所以实际使用中不推荐 Boolean、String、Number、Bigint、Symbol
Object 与 object
- Object 类型(简写为 {})代表 JavaScript 语言里广义的对象,除了 undefined、null,其他都能赋值给 Object 类型,所以不推荐使用。
- Object 或 object 只包含 JavaScript 内置对象原生的属性和方法,用户自定义的属性和方法不存在于这两个类型中。
const o1:Object = { foo: 0 };
const o2:object = { foo: 0 };
o1.toString() // 正确
o1.foo // 报错
o2.toString() // 正确
o2.foo // 报错
undefined 与 null
- undefined、null 既是类型又是值,任何类型的变量都可以赋值为 undefined、null,可以通过编译选项 strictNullChecks 禁止。
值类型
- TypeScript 规定单个值也是一种类型,称为值类型。
- const 声明的变量,如果代码中没有明确注明类型,则退段位值类型。
let x:'hello';
x = 'hello'; // 正确
x = 'world'; // 报错
联合类型
- 多个类型使用 | 符号分隔即是联合类型,可以看成是一种类型放大。
- 在处理联合类型的变量时,需要使用“类型缩小”,即先判断类型,然后按照类型分别处理。
交叉类型
- 多个类型使用 & 符号分隔,主要用于对象合成或为对象添加新属性。
type 命令
- type 命令用来定义一个类型的别名,别名的作用域是块级作用域。
type Age = number;
let age:Age = 55;
- 别名支持使用表达式。
type World = "world";
type Greeting = `hello ${World}`;
- type 命令在编译成 JavaScript 时会被删除。
typeof 运算符
- typeof 运算符在 TypeScript 中返回的是值的 TypeScript 类型,不只限于 JavaScript 中返回的 8 种类型。
数组
let arr:number[] = [1, 2, 3];
let arr:(number|string)[];
let arr:Array<number> = [1, 2, 3];
let arr:Array<number|string>;
- TypeScript 数组所有成员的类型必须相同,其中的成员数量没有限制,没有越界限制。
- 如果数组没有声明类型,TypeScript 会根据成员推断类型。空数组会被推断为 any[],赋值后会更新类型推断。
- TypeScript 允许声明只读数组。
const arr:readonly number[] = [0, 1];
arr[1] = 2; // 报错
arr.push(3); // 报错
delete arr[0]; // 报错
// 其他声明只读数组的方式
const a1:ReadonlyArray<number> = [0, 1];
const a2:Readonly<number[]> = [0, 1];
const arr = [0, 1] as const;
- TypeScript 使用 T[][] 的形式声明二维数组。
元组
- 元组是 TypeScript 特有的数据类型,它表示成员类型可以自由设置的数组,元组声明时必须明确声明每个成员的类型。
- 如果元组声明时没有 ? 或 ...,TypeScript 会推断元组长度
// 数组
let a:number[] = [1];
// 元组
let t:[number] = [1];
声明元组的方式
// ? 表示成员可选,只能在末尾
let a:[number, number?] = [1];
// 扩展运算符表示数量不限
type t2 = [string, ...boolean[], number];
// 不确定成员类型和数量时
type Tuple = [...any[]];
// 声明时可以添加成员名,但没有实际意义
type Color = [
red: number,
green: number,
blue: number
];
const c:Color = [255, 255, 255];
只读元组
// 写法一
type t = readonly [number, string]
// 写法二
type t = Readonly<[number, string]>
symbol 类型
- Symbol 值通过 Symbol 生成,表示独一无二的值,一般用作属性名。
- symbol 类型包含所有的 Symbol 值,但无法表示某个具体值。unique symbol 类型是 symbol 的子类型,表示单个具体的的 Symbol 值。unique symbol 只能使用 const 声明。