首页 > 解决方案 > 为什么 Typescript 编译器认为字符串数组中的元素类型为“从不”?

问题描述

我有一个在 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));
}

标签: typescript

解决方案


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

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

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

正如@jtbandes 所说,既然isNumber告诉 TypeScript 那dateParts[2]是 a number,但 TypeScript 知道split它是一个字符串,它正在尝试应用string & number - 这是never.

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

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

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


推荐阅读