【问题标题】:@typescript-eslint strict-boolean-expressions check for falsy value@typescript-eslint strict-boolean-expressions 检查虚假值
【发布时间】:2021-03-04 12:38:08
【问题描述】:

我最近遇到了一个关于三元检查 number | undefined var 是否为 undefined 的问题,但由于我在编写代码时没有注意,当数字为 0 时,它错误地指责它是一个未定义的值。

然后,我发现了strict-boolean-expressions ESLint 规则。

看起来非常有用且安全,但是,鉴于此示例:

const text: string | undefined = stringOrUndefined1 || stringOrUndefined2 || undefined; // the strings can be empty
if (!text) // I was doing it this way to check if the value was falsy. With the new rule, it complains.
  return;
if (text === undefined || text === '') // This works, but is 4x the length of the one above. I don't want to write the var name more than once
if (!!text == false) // "Unexpected nullable string value in conditional. Please handle the nullish/empty cases explicitly."
if (!!!text) // Same warn as above

有没有什么方法可以在没有冗长的第二个条件并且不禁用规则的情况下快速准确地检查值是否为假,即使只是针对特定行?

我知道可以仅为可空字符串禁用,但这个问题也适用于数字,出于安全原因我想保留这条规则。

【问题讨论】:

  • strict-boolean-expressions 规则的目的是警告隐式转换为布尔值;只有当您确实需要这些隐式转换时,“真实”或“虚假”才重要。 !!text 需要将应用的第一个 ! 隐式转换为布尔值;目前尚不清楚您在哪些情况下需要警告,哪些情况下不需要。
  • 由于这里的答案是有效的,如果不注释代码来解释为什么要使用它们,它们确实不够好使用。我认为检查虚假值的最佳选择是简单且合乎逻辑的text == false JS 允许。但是,Typescript 上已经发布了一个不允许它的错误。

标签: typescript eslint typescript-eslint


【解决方案1】:

您可以尝试像这样使用nullish coalescing operator (??)

if (!(text ?? '')) {}

如果undefinedundefined,则text ?? '' 计算为'',否则计算为text

这等价于:

if (!(text !== null && text !== undefined ? text : '')) {}

【讨论】:

  • 这可能是这种特殊情况的最佳答案。这意味着您的代码清晰明确。使用?? 运算符使您的条件清楚地表示“我正在处理与空字符串情况完全相同的空值情况”。
  • strict-boolean-types 规则 “禁止在需要布尔值的表达式中使用非布尔类型”,因此它应该抱怨表达式 !(text ?? ''),因为 @987654333 @ 的类型是 string,而不是 boolean
  • @kaya3 默认情况下,allowString 选项是true,它允许在布尔表达式中使用字符串。这是安全的,因为只有一个虚假值 ('')。
  • 我明白了。至少,如果该选项被禁用,您可以改写(text ?? '') != ''
【解决方案2】:

如果您想检查一个值的“真实性”,尽管启用了strict-boolean-expressions,您可以为此目的定义帮助函数:

type Falsy = 0 | '' | false | null | undefined

function truthy<T>(x: T): x is Exclude<T, Falsy> {
    return !!(x as any);
}

function falsy<T>(x: T): x is T & Falsy {
    return !(x as any);
}

然后你可以写if(truthy(str)) { ... }if(falsy(str)) { ... } 在你想使用这些测试的地方。

注意这里Falsy类型的定义是不完整的;例如,当Tnumber 时,falsy 将缩小x 为文字类型0,而NaN 也是一个可能的假值。不幸的是,自从Typescript has no NaN literal type 以来没有办法解决这个问题;如果您确实希望代码中包含 NaN 值,这只会是一个问题。

【讨论】:

  • 我认为这不是一个好的解决方案。 strict-boolean-expressions 规则的重点是确保您的检查得到严格而明确的执行。定义这些函数只是围绕规则工作 - 此时您最好允许可空字符串 (github.com/typescript-eslint/typescript-eslint/blob/master/…) 或关闭规则
  • @BradZacher 我认为if(truthy(str)) 对它的作用非常明确,不是吗?
  • 我可以看到一个明显的问题:这些函数不理解类型,这意味着它们不会正确地细化变量(例如:typescriptlang.org/play?#code/…
  • Javascript 语言定义了哪些值是真实的,哪些是虚假的 - 使用这些名称的函数执行其他任何操作都会产生误导。很难想象如何比调用一个名称表明它测试的函数更明确地测试一个值是否为真。 developer.mozilla.org/en-US/docs/Glossary/Truthy
  • “很难想象如何更明确地测试一个值是否真实” --- 通过显式检查! x != null &amp;&amp; x !== '' 更清晰,因为绝对没有歧义。您已经清楚而明确地处理了这两种错误情况,没有人可以将其误读为“他们不了解 lint 错误”、“他们在 linter 周围进行了攻击”或“也许他们没有意识到 '' 是虚假的”。这正是您想要的代码 - 清晰明确。
【解决方案3】:

正如其他人所提到的 - strict-boolean-expressions 的目的是帮助确保您明确处理每个案例,以免您不小心漏掉某些案例。

@cherryblossom 的回答是简洁明了的一种方法 - 它表明您有意以同样的方式处理 nullish 和空字符串情况。

如果您的项目可以对无效字符串进行松散检查 - 您可以根据需要重新配置规则:https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md#allownullablestring


顺便说一句 - 我个人认为在支票中输入额外的几个字符没有问题。清晰明确的处理对您的代码库有好处,最终只需少量额外的击键。

如果您愿意节省击键次数,大多数 IDE(如 VSCode)都可以添加模板化的 sn-ps。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 2016-05-10
    • 2019-05-28
    • 2019-09-21
    相关资源
    最近更新 更多