【问题标题】:Typescript variable type specification打字稿变量类型规范
【发布时间】:2019-09-20 17:03:29
【问题描述】:

我有一个变量可以是 A 类型或 B 类型的情况。然后使用If 我知道变量是什么类型并应用适当的响应。

我收到了 TSLINT 错误。

function checkIfItsAString(foo: String | Number): boolean {
  return foo instanceof String;
}

function example2(foo: String | Number) {
  if (checkIfItsAString(foo)) {
    foo.charAt(5);

    return;
  }
}

我怎么对打字稿说,

从现在开始,这个变量的类型是“字符串”

【问题讨论】:

  • staticIsAnError 真的是type predicate 吗?给minimal reproducible example
  • @jonrsharpe 我添加了一个通用的、可复制的示例
  • 所以它不是类型谓词。编译器不知道您希望该检查缩小类型。
  • @GrégoryNEUT 你可以转换它x as ManuallyCastType 但我建议使用类型谓词checkIfItsAString(foo: String | Number): foo is String 这样你就不必每次都通过转换值手动告诉编译器
  • 你点击我发布的链接了吗?

标签: typescript typescript-typings


【解决方案1】:

编译器无法从boolean 的返回类型checkIfItsAString 推断出任何有用的信息;该函数的 name 告诉其他阅读代码的人类读者您的期望,但这对编译器毫无帮助。

相反,您需要明确指出这是type predicate,即通知编译器它可以使用它来根据结果缩小变量的类型。而不仅仅是boolean,它将返回是否foo is String

function checkIfItsAString(foo: String | Number): foo is String {

实际实现不需要更改,这只是编译器的额外信息。

【讨论】:

    【解决方案2】:

    您可以使用类型谓词让编译器自动缩小类型范围。您的谓词已经起作用,要使其成为类型谓词,您只需说出它对值的含义:

    function checkIfItsAString(foo: String | Number): foo is String {
    //  tell the compiler true means it's a string -> ^^^^^^^^^^^^^
      return foo instanceof String;
    }
    

    这让编译器自动确定类型:

    function example2(foo: String | Number) {
      if (checkIfItsAString(foo)) { //foo is a String
    
        foo.charAt(5);
    
        return;
      }
    
      foo.toFixed(""); //foo is a Number
    }
    

    Live demo on TypeScript Playground

    或者,您可以直接使用in 运算符,这将从类型列表中进行类型消除:

    function example2(foo: String | Number) {
      if ("charAt" in foo) {
      //   ^^^^^^ this only exists on String not on Number, so it's a String
        foo.charAt(5);
    
        return;
      }
    
      foo.toFixed(2); //a number, since it doesn't have "charAt"
    }
    

    Live demo on TypeScript Playground

    这对于一次性更简单的检查更有用,因此您不需要整个谓词来处理它。如果这是一个用例,它可以用来缩小类型。这是一个人为的示例,它使用in 在几个步骤中消除类型。

    /* 
     * ake a Nnumber, String, array of Numbers, or the HTMLCollection array-like:
     * for Number - the value
     * for HTMLCollection - the length
     * for array of number - the sum + the length
     * for string - the length + the trimmed length
     */
    function dummyExample(x : Number | String | Number[] | HTMLCollection) : number {
      if ("length" in x) { // String | Number[] | HTMLCollection
        let totalLength: number = x.length;
    
        if ("slice" in x) { // String | Number[]
          if ("reduce" in x) { // Number[]
            return x.reduce((a: number, b: Number) => a + b.valueOf(), 0) + length;
          } else { // String
            return x.trim().length + totalLength;
          }
        } else { // HTMLCollection
          return totalLength;
        }
      } else { // Number
        return x.valueOf();
      }
    }
    

    Live demo on TypeScript Playground

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-23
      • 2021-04-19
      • 2017-06-10
      • 2018-05-06
      • 2020-03-28
      • 2016-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多