目前正在进行耗尽检查,例如TypeScript中的switch-case
(参见:https://www.typescriptlang.org/docs/handbook/2/narrowing.html)。有一个switch
on shape.kind
属性的例子,看起来像这样:
type Shape = Circle | Square;
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
现在,我的理解是,这个default
检查只存在于编译时检查,* 即 * tsc
将看到这个default
-case,如果有可能发生never = something-else
,例如。如果Shape
是“三角形”,则定义如下:type Shape = Circle | Square | Triangle;
,就像在error-example中一样,那么这将在编译期间抛出错误。
这是否意味着,这些穷举检查只在编译时才有用?是否存在这样的场景,其中这样的耗尽检查default
块可以在运行时执行?
2条答案
按热度按时间agyaoht71#
是的,该块可以在运行时用任何东西调用:例如
getArea("abc" as any)
。在这种情况下,函数将返回字符串"abc"
。完整Playground示例
因此,我总是倾向于在default块中抛出Exception:参见https://stackoverflow.com/a/52913382/1041641
vs3odd8k2#
这种详尽检查实际上只是为了在编译时提供帮助,以确保您已经显式地检查了每个单独的情况。只有当您不愿意让代码失败时,才需要这样的东西。如果你从每一个
case
开始执行return
,并且在它之后不执行return
,那么这是不必要的,因为编译器无论如何都会警告你,如果你犯了一个错误,并不是所有的代码路径都返回一个值:当然,从技术上讲,
default
块中的代码在运行时运行是可能的,但前提是TypeScript类型以某种方式被违反,例如非TS代码调用您的代码,或者TS代码使用不安全的类型Assert或不可靠的any
类型。但这是一个独立的问题这种对潜在的违反期望的处理对于某些用例可能很重要,但是这种详尽的检查不是任何人都应该编写的。
首先,在意外输入的情况下,它只返回输入,其中每个其他代码路径返回
number
。这意味着TypeScript将允许您将其视为number
,并且您刚刚将爆炸移动到代码的后面:也许如果它是
return 0
或其他一些数字,就会有一个合理的论点,即该块正在执行一些有用的运行时清理。接下来,如果你真的关心随机输入,你必须预料到
shape
本身可能不允许你索引它来读取kind
。因此,你可以传入null
或undefined
,代码将在你到达default
块之前在你的函数中爆炸:因此,虽然某些用例可能需要比TypeScript认为需要的更多的运行时检查,但这与手册中的详尽检查几乎没有关系,其目的只是要求编译器在您未能显式处理情况时进行抱怨。
Playground链接到代码