元组 Tuple
数组中元素的数据类型一般是相同的,如果想要 存储不同类型的元素,我们可以使用元组。比如可以定义这样一个元组,有两个元素,第一个元素类型是 string,第二个是 number。
let x: [string, number]; // 定义一个元组
x = ["hello", 2]; // 可以赋值
x = [2, "hello"]; // 不可以赋值,报错,元组中定义的类型和实际传入类型不匹配
console.log(x);
可以通过索引访问元组中的元素,索引从 0 开始,能够获取到对应索引的元素正确的类型:
console.log(x[0].length); // string 类型有 length 属性
console.log(x[1].length); // 报错,number 类型没有 length 属性
枚举
enum 类型在 JavaScript 中没有,是 TypeScript 对它标准数据类型的补充。使用枚举来定义一个集合,集合中每个元素都有一个名称。
// 定义一个颜色枚举,有三种取值
enum Color { Red, Green, Blue };
let color: Color = Color.Red;
console.log(color); // 输出 0
默认情况下,枚举的元素从 0 开始编号,后一个元素的编号默认在前一个元素编号基础之上加 1,如上面 Red 编号为 0,Green 编号为 1,Blue 编号为 2。也可以手动为枚举中部分元素或全部元素指定编号,元素编号不能重复。
enum Color { Red = 1, Green, Blue }
// Red = 1, Green = 2, Blue = 3
enum Color { Red = 1, Green = 3, Blue = 5 }
// Red = 1, Green = 3, Blue = 5
还可以通过枚举元素的编号得到元素的名字:
enum Color { Red = 1, Green, Blue }
let colorName: string = Color[2];
console.log(colorName); // 输出 Green
任意值 any
任意值 any 是 TypeScript 用于定义类型不明确的变量,一般有三种场景可能使用到 any:
- 变量的值来自动态的内容,比如来自用户输入,如果不希望类型检查器对这些值检查,那么可以使用 any 类型来标记变量。
let x: any = 1; // number 类型
x = 'Hello'; // string 类型
x = false; // boolean 类型
- 改写现有代码时,任意值可以在编译时移除类型检查。听起来和
Object很像,但 Object 类型的变量,只能允许对它赋任意值,但不能在它上面调用任意的方法,而 any 则不会做任何检查。
let x: any = 4;
x.canBeExist(); // 正确,canBeExist 在运行时可能存在,编译时不检查
x.toFixed(); // 正确,toFixed 存在,编译时不检查
let y: Object = 4;
y.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
- 定义的数据包含多种数据类型的元素时:
let arr: any[] = [1, false, "Hello"];
arr[1] = 10;
空值 void
void 表示没有任何类型,当一个函数没有返回值时,函数的返回类型是 void,只能为它赋值 undefined 和 null。
function printError(): void {
console.log("error");
}
let x: void = undefined;
x = null;
null 和 undefined
在 TypeScript 里,undefined 的类型是 undefined,null 的类型是 null,和 void 类型,它们的类型作用不大,但值在很多地方都能见到。
默认情况下 null 和 undefined 是所有类型的子类型,也就是说它们可以赋值给任意类型,比如 number。但如果指定了 --strictNullChecks 标记,那么 null 和 undefined 就只能赋值给 void 和它们本身的类型,这可以避免很多问题。如果在一个地方希望传入一个 string 或 null 或 undefined,那么可以使用联合类型 string | null | undefined。
never
never 类型用来表示永不存在的值。返回 never 的函数必须存在无法到达的终点,比如函数一定会抛出异常,或者函数中有死循环。
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
let a: never;
let b: number;
// 编译错误,number 类型不能赋值给 never 类型
a = 12;
// 正确,never 类型可以赋值给 never 类型
a = fail();
// 正确,never 类型可以赋值给 number 类型
b = fail();
never 类型是任意类型的子类型,也可以赋值给任意类型。除了 never 本身,没有类型是 never 的子类型,也没有类型可以赋值给 never,即使是 any 类型也不能赋值给 never 类型。
类型断言
有时开发者比编译器更了解某个值的详细信息,比如一段从服务端返回的数据,类型为 any,其中有很多字段,我们知道这些字段的类型。这时我们可以使用类型断言来告诉编译器自己清楚自己在干什么,它类似于其他语言中的类型转换,但不进行特殊的数据检查和解构,没有运行时的影响,只在编译期起作用(如果类型不对,断言在运行时不会报错)。
类型断言有两种语法:
- 尖括号
<类型>
let value: any = "Hello world";
let length: number = (<string>value).length;
as关键字
let value: any = "Hello world";
let length: number = (value as string).length;
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情