【问题标题】:Why does Typescript compiler think element in string array would be type 'never'?为什么 Typescript 编译器认为字符串数组中的元素类型为“从不”?
【发布时间】:2021-02-19 11:16:13
【问题描述】:

我有一个函数在 Typescript 3.5.3 中编译得很好,但是更新到 3.8.3 后,在编译过程中抛出了一个难以理解的错误。

  import { isNumber, toInteger, padNumber } from './math';

    parse(value: string): NgbDateStruct {
      if (value) {
        const dateParts = value.trim().split('/');
        if (dateParts.length === 3
          && isNumber(dateParts[0])
          && isNumber(dateParts[1])
          && isNumber(dateParts[2])
          // force user to enter 4 digit year
          && dateParts[2].length === 4) {      // <-- fails here
          return {month: toInteger(dateParts[0]), day: toInteger(dateParts[1]), year: toInteger(dateParts[2])};
        }
      }
      return null;
    }

dateParts 变量是一个字符串数组 - 那么为什么在将第三个元素的长度检查为 dateParts[2].length 时,编译器会认为取消引用的值的类型是 never???

编译产生以下错误:

ERROR in src/app/shared/utils/datepicker-parser-formatter.ts:17:25 - error TS2339: Property 'length' does not exist on type 'never'.

17         && dateParts[2].length === 4) {
                           ~~~~~~

isNumber 定义为:

export function isNumber(value: any): value is number {
  return !isNaN(toInteger(value));
}

【问题讨论】:

  • 请用minimal reproducible example 更新您的问题以证明问题,最好还链接到TypeScript playground 中的可运行版本(但在此处也包括所有必要的代码)。
  • isNumber 是如何定义的?我可以通过定义isNumber(x: any): x is number 来重现这个问题,错误是因为number &amp; stringnever。值不能既是数字又是字符串。
  • @jtbandes - 聪明! Nate,如果你的isNumber 是这样定义的,那你就需要解决这个问题。它不应该断言一个字符串是一个数字。 (但前提是 jtbandes 的猜测是正确的。)
  • @jtbandes - 你是对的。我已经发布了 CW 答案,但如果您想发布非 CW 答案,我可以将其删除。如果你愿意,请@ping我。 :-)

标签: typescript


【解决方案1】:

isNumber 定义不正确。它断言任何可以转换为数字的东西都是数字。这是两个不同的东西。正确的定义是这样的:

export function isNumber(value: any): value is number {
  return typeof value === "number" && !isNaN(value);
}

...如果您想要过滤掉NaN 的东西。 (我没有过滤掉 fractionsl 值。)

正如@jtbandes 所说,由于isNumber 告诉TypeScript dateParts[2]number,但TypeScript 从split 知道它是一个字符串,它正在尝试应用string &amp; number——即never .

对于像这样你知道它不是数字的地方,你会想要一个 isNumeric 或类似的类似的东西:

export function isNumeric(value: any): boolean {
  return !isNaN(toInteger(value));
}

请注意,它不会做出断言。

【讨论】:

  • 明白了。所以我们对类型断言太严格了,编译器现在更激进了。我删除了“is number”约束,现在可以编译了。非常感谢!
  • @NateKennedy - 我的荣幸!真正感谢 jtbandes。他们有很好的洞察力。
猜你喜欢
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-10-28
  • 1970-01-01
  • 2019-02-09
  • 2019-11-12
  • 1970-01-01
相关资源
最近更新 更多