本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-05-21
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
会被编译为:
"use strict";
var Days;
(function (Days) {
Days[Days["Sun"] = 0] = "Sun";
Days[Days["Mon"] = 1] = "Mon";
Days[Days["Tue"] = 2] = "Tue";
Days[Days["Wed"] = 3] = "Wed";
Days[Days["Thu"] = 4] = "Thu";
Days[Days["Fri"] = 5] = "Fri";
Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));
枚举成员会被赋值为从0开始递增的数字,同时也会对枚举值到枚举名进行反向映射。
console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true
console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true
未手动赋值的枚举项会接着上一个枚举项递增。
enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 7); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true 自动递增
console.log(Days["Sat"] === 6); // true 自动递增
如果未手动赋值的枚举项与手动赋值的重复了,TypeScript 是无法察觉的。
enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};
console.log(Days["Sun"] === 3); // true
console.log(Days["Wed"] === 3); // true
console.log(Days[3] === "Sun"); // false
console.log(Days[3] === "Wed"); // true
因为会被编译为如下结果:
"use strict";
var Days;
(function (Days) {
Days[Days["Sun"] = 3] = "Sun";
Days[Days["Mon"] = 1] = "Mon";
Days[Days["Tue"] = 2] = "Tue";
Days[Days["Wed"] = 3] = "Wed"; // Days[3] = "Wed" 覆盖了 Days[3] = "Sun"
Days[Days["Thu"] = 4] = "Thu";
Days[Days["Fri"] = 5] = "Fri";
Days[Days["Sat"] = 6] = "Sat";
})(Days || (Days = {}));
手动赋值的枚举项也可以是小数或负数,此时后续没手动赋值的项的递增步长仍为1。
手动赋值的枚举项也可以不是数字,但是无法进行反向映射了。
enum Days {Sun = 7, Mon, Tue, Wed, Thu, Fri, Sat = "S"};
// 最后Sat会被编译为 Days["Sat"] = "S"; 也就无法进行反向映射
此前提到都是常数项,一个典型的计算所得项的例子:
enum Days {
Green,
Blue = "blue".length,
// Red, // error 如果紧接在计算所得项后面的是未手动赋值的项,那么它就会因为无法获得初始值而报错
};
编译为:
(function (Days) {
Days[Days["Green"] = 0] = "Green";
Days[Days["Blue"] = "blue".length] = "Blue";
})(Days || (Days = {}));
常数枚举是指使用 const enum
定义的枚举,会在编译阶段被删除,代码中使用到的,会在编译阶段直接用枚举值替换。
const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
会被编译为:
"use strict";
let directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
并且常数枚举不能包含计算成员,否则会报错。
外部枚举 (Ambient Enums) 是使用 (declare enum) 定义的枚举类型,常出现在声明文件中,在编译结果会被删除。
declare enum Days {Sun, Mon}
declare const enum Directions {
Up,
Down,
Left,
Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
var a = 1;
编译结果只有 var a = 1
,也不会有 let directions
这一行。
数组合并了相同类型的对象,而元祖 (Tuple) 合并了不同类型的对象。
let tom: [string, number] = ['Tom', 24];
当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型。
let tom: [string, number];
tom = ['Tom', 24];
tom.push('Jack')
tom.push(25)
// tom.push(true) // error 类型“boolean”的参数不能赋给类型“string | number”的参数。
类型别名用来给一个类型起一个新名字;
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
}
return n();
}
字符串字面量类型用来约束取值只能取某几个字符串中的一个。与类型别名一样使用type
定义。
type E = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: E) {
// do something
}
handleEvent(document.querySelector('.a') as Element, 'click')
// handleEvent(document.querySelector('.a') as Element, 'dbclick')
// error 类型“"dbclick"”的参数不能赋给类型“E”的参数。
keyof,后面接类型,从一个类型中取出所有的key组成一个字符串字面量类型,即结果是字符串字面量类型。
interface Person {
name: string;
age: number;
}
type PersonKey = keyof Person;
function getValue(p: Person, key: PersonKey): string | number {
return p[key];
}
let a : Person = {
name: 'jack',
age: 20
}
getValue(a, 'age')
getValue(a, 'name')
// getValue(a, 'sex') // 类型“"sex"”的参数不能赋给类型“keyof Person”的参数。
多在泛型中使用
function getVal<T>(obj: T, key: keyof T): T[keyof T] {
return obj[key]
}
getVal(a, 'age')
getVal(a, 'name')
// getVal(a, 'sex') // 类型“"sex"”的参数不能赋给类型“keyof Person”的参数。
typeof 后面接值,取出一个值的类型,即结果是类型。
var a = {
name: 'jack',
age: 24,
}
var b: typeof a = {
name: 'tom',
age: 18
// sex: 'males' 不能将类型“{ name: string; age: number; sex: string; }”分配给类型“{ name: string; age: number; }”
}
// a 和 b 的类型,都是
// {
// name: string;
// age: number;
// }