将枚举转换为自定义文字数组
Converting an enum to an array of custom literals
假设这样:
export enum Day {
Monday = 111,
Tuesday = 222,
Wednesday = 333,
Thursday = 444,
Friday = 555,
Saturday = 666,
Sunday = 777,
}
Object.values(Day)
.filter(v => typeof v === 'number') // or filter(Number)
.map(numeric => console.log('numeric', numeric))
// more code to come
我正在尝试从枚举中构建一个自定义对象数组,例如 { id: 111, label: 'Monday' }
,但我正在努力处理类型。
当鼠标悬停在 numeric
上时,我希望类型为 number
,或者可能是 Day
,但从未与 | string
联合,因为我正在过滤掉字符串就在它之前。
这是为什么?
关键在于 TypeScript 如何将 enum
代码转换为 JavaScript:
export var Day;
(function (Day) {
Day[Day["Monday"] = 111] = "Monday";
Day[Day["Tuesday"] = 222] = "Tuesday";
Day[Day["Wednesday"] = 333] = "Wednesday";
Day[Day["Thursday"] = 444] = "Thursday";
Day[Day["Friday"] = 555] = "Friday";
Day[Day["Saturday"] = 666] = "Saturday";
Day[Day["Sunday"] = 777] = "Sunday";
})(Day || (Day = {}));
您可以通过查看 TypeScript Playground
中的 JS 输出自行验证这一点
基本上,它确保可以从任一方向查找枚举的值。什么是 Day.Monday
?为什么是 111
。但是 Day['111']
是什么?啊,是'Monday'
.
这是有效的,因为内部方括号中的表达式解析为分配的值。例如,Day["Monday"] = 111
解析为 111
,因此 Day[Day["Monday"] = 111] = "Monday";
本质上是 shorthand for:
Day["Monday"] = 111;
Day[111] = "Monday";
因此,当您将 Day
传递给 Object.values
时,您并不会像您预期的那样得到 [111, 222, 333, 444, 555, 666, 777]
。相反,您得到 ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", 111, 222, 333, 444, 555, 666, 777]
。 TypeScript 将其解释为 (string | Day)[]
.
类型
如果您希望打字稿推断 numeric
的实际类型,您可以在 map
之前使用类型保护,例如
function isNumber(v: unknown): v is number {
return typeof v === 'number'
}
Object.values(Day)
.filter(isNumber) // or filter(Number)
.map(numeric => console.log('numeric', numeric)) // numeric is number
假设这样:
export enum Day {
Monday = 111,
Tuesday = 222,
Wednesday = 333,
Thursday = 444,
Friday = 555,
Saturday = 666,
Sunday = 777,
}
Object.values(Day)
.filter(v => typeof v === 'number') // or filter(Number)
.map(numeric => console.log('numeric', numeric))
// more code to come
我正在尝试从枚举中构建一个自定义对象数组,例如 { id: 111, label: 'Monday' }
,但我正在努力处理类型。
当鼠标悬停在 numeric
上时,我希望类型为 number
,或者可能是 Day
,但从未与 | string
联合,因为我正在过滤掉字符串就在它之前。
这是为什么?
关键在于 TypeScript 如何将 enum
代码转换为 JavaScript:
export var Day;
(function (Day) {
Day[Day["Monday"] = 111] = "Monday";
Day[Day["Tuesday"] = 222] = "Tuesday";
Day[Day["Wednesday"] = 333] = "Wednesday";
Day[Day["Thursday"] = 444] = "Thursday";
Day[Day["Friday"] = 555] = "Friday";
Day[Day["Saturday"] = 666] = "Saturday";
Day[Day["Sunday"] = 777] = "Sunday";
})(Day || (Day = {}));
您可以通过查看 TypeScript Playground
中的 JS 输出自行验证这一点基本上,它确保可以从任一方向查找枚举的值。什么是 Day.Monday
?为什么是 111
。但是 Day['111']
是什么?啊,是'Monday'
.
这是有效的,因为内部方括号中的表达式解析为分配的值。例如,Day["Monday"] = 111
解析为 111
,因此 Day[Day["Monday"] = 111] = "Monday";
本质上是 shorthand for:
Day["Monday"] = 111;
Day[111] = "Monday";
因此,当您将 Day
传递给 Object.values
时,您并不会像您预期的那样得到 [111, 222, 333, 444, 555, 666, 777]
。相反,您得到 ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", 111, 222, 333, 444, 555, 666, 777]
。 TypeScript 将其解释为 (string | Day)[]
.
如果您希望打字稿推断 numeric
的实际类型,您可以在 map
之前使用类型保护,例如
function isNumber(v: unknown): v is number {
return typeof v === 'number'
}
Object.values(Day)
.filter(isNumber) // or filter(Number)
.map(numeric => console.log('numeric', numeric)) // numeric is number