扩展类型-枚举
扩展类型:类型别名、枚举、接口、类;
枚举通常用于约束某个变量的取值范围;字面量和联合类型配合使用,也可以达到同样的目标;
字面量类型的问题
在类型约束位置,会产生重复代码 (可以使用类型别名解决该问题);
逻辑含义和真实的值产生了混淆,会导致当修改真实值的时候,产生大量的修改 (eg: type gender = “男” | “女”,之后修改 “男” => 帅哥,需要修改大量代码);
字面量类型不会进入到编译结果;
枚举
枚举的规则
枚举的字段值可以是 字符串 或 数字;
数字枚举的值会 自动自增;
被数字枚举约束的变量,可以直接赋值为数字;
数字枚举的编译结果 和 字符串枚举有差异;
常量枚举
加上 const 就是常量枚举,不会侵入编译结果;
常量枚举只能单向获取值;
const enum PostStatus {
Draft = 6,
Unpublished, // => 7
Published = 'aaa',
}
console.log(PostStatus['Draft']); // 6
console.log(PostStatus['Published']); // aaa
// 编译之后,会把枚举移除掉
console.log(6 /* PostStatus['Draft'] */); // 6
console.log("aaa" /* PostStatus['Published'] */); // aaa
数字/字符串枚举
数字枚举可双向获取枚举值
数字枚举,枚举值自动基于前一个值自增
enum PostStatus {
Draft = 6,
Unpublished, // => 7
Published = 'aaa',
}
console.log(PostStatus[6]); // Draft => 使用索引器的方式获取 key
console.log(PostStatus['Draft']); // 6
console.log(PostStatus['aaa']); // undefined
console.log(PostStatus['Published']); // aaa
// 编译之后,数字枚举会形成双向的健值对对象,不会移除枚举
var PostStatus;
(function (PostStatus) {
PostStatus[PostStatus["Draft"] = 6] = "Draft";
PostStatus[PostStatus["Unpublished"] = 7] = "Unpublished";
PostStatus["Published"] = "aaa";
})(PostStatus || (PostStatus = {}));
console.log(PostStatus[6]); // Draft => 使用索引器的方式获取 key
console.log(PostStatus['Draft']); // 6
console.log(PostStatus['aaa']); // undefined
console.log(PostStatus['Published']); // aaa
最佳实践
尽量不要在一个枚举中既出现字符串字段,又出现数字字段;
使用枚举时,尽量使用枚举字段的名称,而不使用真实的值;
案例
位枚举(枚举的位运算)
针对的数字枚举;
位运算:两个数字换算成二进制后进行的运算;
enum Permission {
Read = 1, // 0001
Write = 2, // 0010
Create = 4, // 0100
Delete = 8 // 1000
}
// 1. 权限组合
let p: Permission = Permission.Read | Permission.Write; // 0001 | 0010 => 0011
// 2. 判断是否拥有某个权限
function hasPermission(target: Permission, per: Permission) {
// (0011 & 0010) === 0010,存在 0010 这个权限
return (target & per) === per;
}
// 3. 如何删除某个权限
p = p ^ Permission.Write; // 0011 ^ 0010 => 0001,删除了 0010 这个权限
console.log(hasPermission(p, Permission.Write));
使用枚举优化扑克牌程序
enum Color {
heart = "♥",
spade = "♠",
club = "♣",
diamond = "♦"
}
enum Mark {
one = "A",
two = "2",
three = "3",
four = "4",
five = "5",
six = "6",
seven = "7",
eight = "8",
nine = "9",
ten = "10",
eleven = "J",
twelve = "Q",
king = "K"
}
type NormalCard = {
color: Color
mark: Mark
}
type Deck = NormalCard[]
function createDeck(): Deck {
const deck: Deck = [];
const marks = Object.values(Mark)
const colors = Object.values(Color)
for (const m of marks) {
for (const c of colors) {
deck.push({ color: c, mark: m });
}
}
return deck;
}
function printDeck(deck: Deck) {
let result = "\n";
deck.forEach((card, i) => {
let str = card.color + card.mark;
result += str + "\t";
if ((i + 1) % 4 === 0) {
result += "\n";
}
})
console.log(result);
}
const deck = createDeck();
printDeck(deck);
TypeScript👉 never 类型
上一篇