扩展类型包括:类型别名、枚举、接口、类
枚举就是一个个的罗列,映射
枚举通常用于约束某个变量的取值范围。字面量和联合类型配合使用,也可以达到同样目标,但是有问题。
字面量类型的问题
- 在类型约束位置,会产生重复代码。可以使用类型别名解决该问题。
- 逻辑含义和真实的值(帅哥/美女, 男/女)产生了混淆,会导致当修改真实值的时候,产生大量修改。
- 就是说因为你是字面量,在多处写了字面量,到时修改真实值时,就会产生大量修改
- 字面量类型不会进入到编译结果(这些字面量类型信息直接丢失了)
枚举类型的使用
如何定义一个枚举
enum meijuname{
枚举字段1 = 值1,//左边是逻辑名称,右边是真实值
枚举字段2 = 值2,
}
let gender1: Gender = Gender.male;
let gender2: Gender = Gender.female;
枚举的好处:
- 使用的是逻辑名称
- tsc后会进入编译结果中,这就很恐怖很nb了,利用的是IIFE&&全局变量—对象.属性名
枚举的规则:
- 枚举的字段可以是字符串或数字
- 数字枚举的值会自动自增(默认从0开始),如果中间有个值跳跃了,后面的会接着跳跃的值继续自增
- 被数字枚举约束的变量,可以直接赋值,不会报错,但这就会留下隐患
- 数字枚举 和 字符串枚举 的编译结果有差异!
```javascript
var Gender;
(function (Gender) {
Gender[“male”] = “\u7537”;
Gender[“female”] = “\u5973”;
})(Gender || (Gender = {}));
let gender1 = Gender.male;
let gender2 = Gender.female;
console.log(gender1, gender2);
function printGenders() {
const vals = Object.values(Gender);
vals.forEach(v => console.log(v));
}
var Level;
(function (Level) {
Level[Level[“level1”] = 2] = “level1”;
Level[Level[“level2”] = 3] = “level2”;
Level[Level[“level3”] = 4] = “level3”;
})(Level || (Level = {}));
/**
- 相当于是编译成为了
- {
- level1: 2,
- level2: 3,
- level3: 4,
- 2:’level1’,
- 3:’level2’,
- 4:’level3’,
- } */ let level1 = Level.level1; let level2 = Level.level2; let level3 = Level.level3; level3 = 8; console.log(level1, level2, level3);
<a name="tygeS"></a>
## 枚举的最佳实践
1. 尽量**不要在**一个枚举中**同时出现** 字符串字段和数字字段
1. 尽量**使用枚举字段的名称**,而不使用真实的值
<a name="ZzynG"></a>
# 利用枚举类型改进扑克牌程序
```typescript
//一副牌
type Deck = NormalCard[];
//牌号
enum Mark {
A = 'A',
two = '2',
three = '3',
four = '4',
five = '5',
six = '6',
seven = '7',
eight = '8',
nine = '9',
ten = '10',
eleven = 'J',
twelve = 'Q',
thirteen = 'K',
}
//花色
enum Color {
heart = '红心♥️',
spade = '♠️',
diamond = '♦️',
club = '♣️',
};
//一张牌
type NormalCard = {
// color: string,//花色, 进行一下限制, 因为总共就四种
color: Color,
mark: Mark,//序号
};
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){
deck.forEach((card, i)=>{
let str = card.color + ' ' +card.mark;
console.log(str);
if((i+1)%4 === 0){
console.log('\n');
}
});
}
const deck = createDeck();
printDeck(deck);
扩展知识:位枚举(枚举的位运算)
主要是针对 数字枚举
//1. 如何组合权限, 利用 按位或 运算, 有 1 出 1
let p = Permission.Read | Permission.Write;//0011
console.log(p);//3
//2. 如何判断一个权限是否拥有某个权限, 利用 按位与 后, 判断是否与sonPer相等
//比如判断0101是否含有0001权限
function hasPermission(target: Permission, sonPer: Permission) {
return (target & sonPer) === sonPer;
}
console.log(hasPermission(p, Permission.Write));//看p是否有write权限
//3. 如何删除某个权限, 利用按位疑惑,相同为0不同为1
p = p ^ Permission.Write;
console.log(p);//1
- 组合权限:按位或,A | B
- A权限是否拥有B权限:(A & B) === B
- 删除权限:A ^ B