【问题标题】:Is it possible to let the interpreter know my method checks for undefined/null in TypeScript是否可以让解释器知道我的方法在 TypeScript 中检查 undefined/null
【发布时间】:2021-10-04 13:26:52
【问题描述】:

例如,我有一个方法isEmpty 检查是否有任何内容为空、null 或未定义,如果是则返回 true。

但是在 TypeScript 中,它不会让解释器知道是这种情况,我的 IDE (WebStorm) 中出现红色下划线

示例代码

let str: string | undefined = undefined
if (!isEmpty(str)) {
   doSomeWorkFunction(str) // this line is shows the error 'string | undefined is not assignable to type string
}

但是如果代码是

let str: string | undefined = undefined
if (str) {
    doSomeWorkFunction(str) // no error because the interpreter knows I checked the value
}

我想避免的解决方法是

let str: string | undefined = undefined
if (!isEmpty(str)){
    // @ts-ignore
    doSomeWorkFunction(str) // no error since ts is now ignoring this error
}

我怎样才能继续保持 TypeScript 严格的空检查,而不必忽略这样的问题。

【问题讨论】:

    标签: javascript typescript webstorm


    【解决方案1】:

    TypeScript 有一个称为“类型保护”的功能可以在这种情况下提供帮助:https://www.typescriptlang.org/docs/handbook/advanced-types.html。具体来说,它让您告诉编译器返回类型不仅仅是boolean,而是boolean,这意味着特定于输入的类型。例如,你可以像这样转换一个函数

    function isDefinedString(input: string | undefined): boolean
    

    变成这样的函数:

    function isDefinedString(input: string | undefined): input is string
    

    返回类型仍然是boolean,但现在编译器将假定输入具体是string,而不是参数声明允许的任何其他类型(在本例中为undefined)。

    尝试在您现有的 isEmpty 函数声明中使用此签名。虽然不需要让它工作,但因为您要将这个额外的上下文添加到函数签名中,所以我建议更改 isEmpty 的名称以反映其检查空性和变量是否已定义的双重目的。

    编辑: 返回类型信息的一个警告是,返回 false 将使编译器假定对象不是该类型。在上面的例子中,如果isDefinedString 返回 false 那么编译器将假定它不是一个字符串。这会遇到any 或泛型参数的问题,因为返回 false 会有效地告诉编译器没有满足您标准的类型(或者用编译器的话来说,“从来没有”类型)。虽然这不会直接导致错误,但编译器没有与您的对象一起使用的类型这一事实意味着您无法对由您的类型保护返回 false 触发的 if/else 分支中的对象执行任何有意义的操作。因此,如果您使用诸如any 或泛型之类的宽泛类型,则如果您打算做一些有意义的事情,那么您将希望将您的类型保护说的内容限制为input is (null | undefined)input is MySpecificInterface。虚假案件。这种技巧也可能表明您希望将验证分为两个检查:

    if(typeGuard(myObject)) {
      if(isValid(myObject)) {
        // do something with valid object
      } else {
        // do something with invalid object
      }
    }
    // do nothing without an object to act upon
    

    【讨论】:

    • 如果输入类型是 any 或 例如输入未知时会怎样
    • 我能够通过添加基本类型作为输入以及外部的泛型 isEmpty<T>( obj: T | string | number | bigint | boolean | undefined | null ): obj is T 来使其工作
    • 实际上它有问题检查说我不能使用我刚刚检查过的那个项目,因为它是“从不”我该如何解决这个问题?
    • 听起来编译器无法确定哪些类型可以匹配T。为了提供帮助,我需要查看导致问题的代码。我不确定在这种情况下使用泛型类型是否正确。你如何定义任何类型是否为空?它对字符串或数组有意义,但布尔值不能为“空”。如果您只需要检查一个对象是否已定义/非空,那么您可以使用像myObject != null 这样简单的东西。如果您有仅适用于某些类型的特定验证,那么您可以使用类型保护。
    • 我找到了答案github.com/microsoft/TypeScript/issues/… 让我这样做function isEmpty<T>( obj: T | null | undefined ): obj is (null | undefined) 如果您能对此进行解释,我可以接受您的回答。使用这个作为内部stackoverflow.com/a/28953167/4807889,通过解释只是将此信息添加到您的答案中,因为您引导我朝着正确的方向前进。
    猜你喜欢
    • 1970-01-01
    • 2022-11-17
    • 2018-12-16
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    相关资源
    最近更新 更多