TypeScript 建议:对始终为假的类型保护发出警告

dbf7pr2w  于 6个月前  发布在  TypeScript
关注(0)|答案(5)|浏览(68)

搜索词

类型保护 always-false 警告

建议

当类型保护总是为 false 时,受保护的变量在函数体内是类型 never。虽然你实际上无法在 never 上查找任何属性,但你可以将其传递给任何地方或分配给任何事物,并且绝对没有警告。使用与保护不重叠的参数调用类型保护函数应该产生警告。

用例

我立即的动机是 #24436(评论),其中如果 Number.isFinite 可以写成类型保护(这还需要一个更窄的 number 子类型,例如 #32188 ),那么它可以轻松地允许使用 number|string 调用,但不需要额外的技巧来警告如果使用保证不是 number 的情况。
一般来说,没有很好的理由调用总是为 false 的类型保护。这与总是为 true 的情况不同,在那种情况下防御性编程才发挥作用。

示例

示例:

declare const x: string;
if (isNumber(x)) { // Should warn: "condition is always false"
    usePrivate(x);
}

如果 usePrivate 需要一个此范围无法访问以构造的私有类型,那么如果这段代码能 在某个地方 发出警告就好了。然而,目前它只是将 x 缩小到 never 并允许你随心所欲地使用它。

检查清单

我的建议满足以下准则:

  • 这不会对现有的 TypeScript/JavaScript 代码造成破坏性的更改
  • 我对于这个会破坏多少东西没有很好的感觉,但我预计任何破坏都会暴露出合法的错误。
  • 这不会改变现有 JavaScript 代码的运行时行为
  • 这个可以在不根据表达式的类型生成不同的 JS 的情况下实现
  • 这不是一个运行时特性(例如库功能、JavaScript 输出非 ECMAScript 语法等)
  • 这个特性将与 TypeScript's Design Goals 的其他部分保持一致。
guz6ccqo

guz6ccqo2#

无论如何,Step提到了这一点。
这与总是为真的情况有所不同,即防御性编程发挥作用。
isString() 始终是 (根据类型系统),只是之后取反了。

g6ll5ycj

g6ll5ycj3#

我认为,将防御性检查始终以始终为真的格式编写是不合理的。你可以很容易地想象这样写:

function fn(x: number) {
  if (isNullOrUndefined(x)) Debug.fail("x must be provided");
}

不清楚这与OP中的情况有何不同。

cx6n0qe3

cx6n0qe34#

这是一个很好的观点,尽管我怀疑这种情况要少得多。总是可以选择将类型转换为unknown,尽管这并不是特别令人满意。对于这个来说,将其视为类型保护器也不太相关,因为它实际上并没有缩小任何东西的范围。

@RyanCavanaugh - 我的潜在动机是你关于想要警告Number.isFinite(shouldNeverBeANumber)的评论,这在某种程度上是相似的 - 我认为你在这里的例子更具说服力,因为它涉及到null/undefined,我们自然地理解它们通常是类型系统的可能例外。

也许一个更聪明的方法是在typeguard(x | undefined | null)始终为false时发出警告。它缺乏一定的对称性,而且通常来说,聪明的做法是不好,但它似乎通过了一点更好的测试...

brtdzjyr

brtdzjyr5#

我猜想有人可能会声明这个检查为

declare function isNullOrUndefined(x: any): x is null | undefined;

但这似乎没有什么用处;你什么时候需要一个保证为nullish的值呢?如果你不把它当作类型保护器使用...那么这就是它与OP的区别。问题是关于对总是为false的类型 predicate 调用的警告。
我想不出我曾经见过一个类型保护器在正常操作中总是为假的情况。泛型防御性boolean检查,当然有,但是没有总是为假的类型保护器。

相关问题