【问题标题】:How to indicate that path is unreachable in TypeScript如何在 TypeScript 中指示路径不可访问
【发布时间】:2018-10-15 01:36:00
【问题描述】:

我有一些基本上看起来像这样的 Typescript 代码

if( ... ) 
   result  = $(document.createElement("div")) ;
} else if( ... ) {
    result  = $(document.createElement("div")) ;
} else {
    assert.unreachable( "Unknown label in buildHTML.") ;
}
result.attr( "data-childNumber", childNumber.toString() ) ; 

assert.unreachable的返回类型是never。

最后一行显示“变量‘结果’在被赋值之前被使用。”有一个错误。

在我看来,来自assert.unreachable 的never 结果应该告诉编译器else 部分没有路径。

我知道我可以通过在else 末尾添加throw null; 来抑制错误,但这似乎不优雅。

unreachable 的定义中也出现了类似的问题。看起来像这样

export function unreachable( message? : string ) : never {
    if( message===undefined ) message = "Unreachable code reached." ;
    else message = "Unreachable code reached: "+message ;
    raiseTheAlarm( message ) ;
}

raiseTheAlarm 的结果类型为never。在这种情况下,我收到一个错误“返回 'never' 的函数不能有可到达的端点。”

我通过在调用raiseTheAlarm 之前添加return 关键字来解决此问题。这看起来有点奇怪。 (当然,电话之后的throw null; 也可以。)

有没有更好的方法告诉编译器代码中的某个点不可达?

【问题讨论】:

  • tsc编译器版本为2.3.4
  • 对assert.unreachable的调用确实阻止了后续代码的执行,因为对assert.unreachable函数的调用永远不会返回。
  • 让我了解never 类型。我完全错过了这个功能。很抱歉造成混乱。

标签: typescript


【解决方案1】:

在我看来,assert.unreachable 的 never 结果应该 告诉编译器 else 部分没有路径。

反之亦然。当编译器检测到某些路径无法访问时,它会推断该路径中引用的变量的never 类型(如果可以)。您可以使用它来强制您的代码处理枚举或联合类型的所有可能值,如here 所述。

但是,编译器在检查变量在初始化之前未使用时,不会使用某些路径不可访问的信息。解决方案很简单 - 您可以将 never 值分配给无法访问路径中的该变量。正如上面链接的答案中所解释的,never 可分配给专门为此目的的任何其他类型。

if( ... ) 
   result  = $(document.createElement("div")) ;
} else if( ... ) {
    result  = $(document.createElement("div")) ;
} else {
    result = assert.unreachable( "Unknown label in buildHTML.") ;
}
result.attr( "data-childNumber", childNumber.toString() ) ; 

unreachable 函数的问题以同样的方式修复 - 它应该有

return raiseTheAlarm( message ) ;

作为最后的陈述。

【讨论】:

  • 很好的答案。我有一个小问题。您说“但是,编译器在检查变量在初始化之前未使用时,不会使用某些路径无法访问的信息。”但是添加throw null; 会抑制错误的事实表明编译器有时会这样做。
  • 添加throw 或return 明确告诉编译器在使用前没有未分配result 的路径。一种可能的解释是 unreachable code analysis is entirely separate from analysis for detecting use before assignment 他们可能应该在 github 上对此有问题。
【解决方案2】:

至少有三个选项

(a)

else {
    return assert.unreachable( "Unknown label in buildHTML.") ;
}

(b)(来自@artem 的回答)

else {
    result = assert.unreachable( "Unknown label in buildHTML.") ;
}

(c)

else {
    assert.unreachable( "Unknown label in buildHTML.") ;
    throw null ;
}

我选择了选项 (a)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 2013-06-24
    • 2012-07-14
    相关资源
    最近更新 更多