问题起源是一段代码没有达到预期效果:
enum Weekday {
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
//100 已经超过了Weekday范围(1 ~ 7),但是并没有报错
const a: Weekday = 100;
研究期间又发现了新问题:
enum Position {
TOP = "top",
BOTTOM = "bottom",
}
//报错,不能将类型“"top"”分配给类型“Position”
const b: Position = "top";
//报错,不能将类型“"top"”分配给类型“Position.TOP”。
const c: Position.TOP = "top";
奇了怪了!难道 enum
不是这么用的?
经过一番查找,发现这是一个历史原因。有大量issue(至少几十个吧)反馈 enum
的反人类设计,开发者回复此问题改造很大,暂时不会修改。
I don't see this as enough to change our mind here; this would be a very large breaking change and would imply bifurcating flag and nonflag enums. See #17734, #21546, #11559, #15591, #8020, #18409, etc.
后来在#32690中找到了一种解决方法:
namespace MyEnum {
export const Zero = 0;
export type Zero = typeof Zero;
export const One = 1;
export type One = typeof One;
}
type MyEnum = typeof MyEnum[keyof typeof MyEnum];
const foo: MyEnum.Zero = 0 // okay as expected
const bar: MyEnum.Zero = 1 // error as expected
试了一下确实可以解决问题,但是代码看的不是很明白,主要是 typeof
和 keyof
,我查了一下文档:
-
typeof
用来获取一个变量的类型:
interface Person {
name: string;
age: number;
}
const sem: Person = { name: "semlinker", age: 30 };
type Sem = typeof sem; // type Sem = Person
-
keyof
用来获取某种类型的所有键
interface Person {
name: string;
age: number;
}
type PersonProperties = keyof Person; //type PersonProperties = "name" | "age"
有了基础知识,继续分析大佬的解决方法,拆解和注释如下:
namespace MyEnum {
export const Zero = 0;
export type Zero = typeof Zero;
export const One = 1;
export type One = typeof One;
}
type A = keyof typeof MyEnum; // type A = "Zero" | "One"
type MyEnum = typeof MyEnum[A]; // type MyEnum = 0 | 1
const foo: MyEnum.Zero = 0 // okay as expected
const bar: MyEnum.Zero = 1 // error as expected
const coo: MyEnum = 3 // error as expected
研究过程中,发现一些资料,建议阅读:
https://www.cnblogs.com/lyraLee/p/12398208.html
https://stackoverflow.com/questions/17380845/how-do-i-convert-a-string-to-enum-in-typescript
https://jkchao.github.io/typescript-book-chinese/typings/enums.html#%E5%BC%80%E6%94%BE%E5%BC%8F%E6%9E%9A%E4%B8%BE
网友评论