gpt4 book ai didi

typescript - 您如何使用引用其他字符串枚举的字符串枚举在 Typescript 中进行详尽的 switch case

转载 作者:行者123 更新时间:2023-12-04 11:47:27 25 4
gpt4 key购买 nike

我有一个字符串枚举,它是另一个字符串枚举值的子集。我正在尝试对前者进行详尽的切换案例。

这是我试图在 Typescript 中表示的构造的一个人为示例

const enum Color {
BLUE = 'Blue',
YELLOW = 'Yellow',
RED = 'Red'
}

const enum SupportedColor {
BLUE = Color.BLUE,
YELLOW = Color.YELLOW
}


function doSomething(colorFromOutsideInput: string): boolean {
const supportedColor: SupportedColor = (colorFromOutsideInput as unknown) as SupportedColor;
switch (supportedColor) {
case SupportedColor.BLUE:
return true;
case SupportedColor.YELLOW:
return true;
default:
return invalidColor(supportedColor);
}
}

function invalidColor(supportedColor: never): never {
throw new Error();
}

在这段代码中, switch case 中的默认值编译失败
Argument of type 'SupportedColor' is not assignable to parameter of type 'never'.

如果我在 Color 上做这个开关案例枚举而不是 SupportedColor枚举,它会起作用。

基于对 typescript 文档的阅读,我没有看到编译器为什么会以不同的方式对待这两个枚举的证据,因为它们评估为相同的字符串。

最佳答案

我会尽量减少这个例子,但提出的问题是一样的。

枚举,其中每个枚举值都具有显式 string literalnumeric literal输入像 union types , 可以通过 type guards 缩小.这种枚举称为 union enum :

// union enum
const enum SupportedColor {
BLUE = "Blue",
YELLOW = "Yellow"
}

// no error here
function doSomething(supportedColor: SupportedColor): boolean {
switch (supportedColor) {
case SupportedColor.BLUE:
supportedColor // SupportedColor.BLUE
return true;
case SupportedColor.YELLOW:
supportedColor // SupportedColor.YELLOW
return true;
}
//supportedColor // never
//~~~~~~~~~~~~~ <-- unreachable code
}

在上面的代码中,编译器识别出 switch声明是详尽无遗的,因为 supportedColor类型 SupportedColor可以通过控制流分析来缩小。型号 SupportedColor相当于联合 SupportedColor.BLUE | SupportedColor.YELLOW .

于是里面各种 case s, supportedColor依次缩小到类型 SupportedColor.BLUESupportedColor.YELLOW .后 switch语句结束,编译器知道 supportedColor类型为 never , 因为两者都是 SupportedColor.BLUESupportedColor.YELLOW已经被联盟过滤掉了。如果您取消注释 switch 之后的代码块,编译器甚至会提示它在 TS3.7+ 中无法访问。

因此所有代码路径都返回一个值,编译器不会提示。

现在考虑当您更改要计算的枚举值而不是文字时会发生什么:
const enum Color {
BLUE = 'Blue',
YELLOW = 'Yellow',
RED = 'Red'
}

// calculated enum
const enum SupportedColor {
BLUE = Color.BLUE,
YELLOW = Color.YELLOW
}

function doSomething(supportedColor: SupportedColor): boolean { // error!
// --------------------------------------------> ~~~~~~~
// function lacks ending return statement
switch (supportedColor) {
case SupportedColor.BLUE:
supportedColor // SupportedColor
return true;
case SupportedColor.YELLOW:
supportedColor // SupportedColor
return true;
}
supportedColor // SupportedColor
}

这里的枚举类型 SupportedColor不再被视为联合类型。计算的枚举不是联合枚举。因此编译器无法缩小或过滤 supportedColor 的类型。在 switch 中或之后陈述。类型保持 SupportedColor整个过程。和 switch语句不被视为详尽无遗,并且编译器提示该函数并不总是返回一个值。

这解释了发生了什么,并且联合枚举的文档链接确实说联合枚举和计算枚举是不同的。所以它被记录在案。但是文档中没有解释的是为什么计算的枚举不被视为联合。也就是说:它按设计工作,但是否有人真的更喜欢这样,还是只是设计限制?

我能找到的最接近规范答案的是 GitHub 问题 microsoft/TypeScript#22709引用里面的一些 session 记录 microsoft/TypeScript#26241 .这些笔记是:

  • There are actually many kinds of enums under the hood
  • Union enums only get created when only bare literals (or nothing) are initializers
  • These kinds of enums behave differently
  • You might want one or the other and this is how you choose
  • Working As Intended; would be a Breaking Change


因此 TS 团队表示,非联合枚举实际上有时是可取的,并且在此处进行更改会破坏依赖于当前行为的现有代码。它不是特别令人满意的答案,因为它没有描述人们想要非联合枚举的用例,但它仍然是一个答案:这是故意的。如果您想要联合枚举,请使用文字而不是计算值。

好的,希望有帮助;祝你好运!

Playground link to code

关于typescript - 您如何使用引用其他字符串枚举的字符串枚举在 Typescript 中进行详尽的 switch case,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60610859/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com