令人信服的TypeScript编译器,过滤后的数组不包含空值

时间:2018-03-03 21:57:08

标签: typescript

我遇到了一个有趣的案例,TypeScript编译器(带有strictNullChecks === true)不允许我将带有空值的数组传递给到需要数字数组的函数。

以下是显示问题的代码示例:

class Test {
    constructor() {
        const values = [1, 2, null, 4].filter(x => x);
        this.printNumberArray(values);
    }

    printNumberArray(values: number[]) {
        console.log(values);
    }
}

这会导致红色波浪线出现在values下,并显示以下错误:

Argument of type '(number | null)[]' is not assignable to parameter of type 'number[]'.
  Type 'number | null' is not assignable to type 'number'.
    Type 'null' is not assignable to type 'number'.

const values: (number | null)[]

filter保证消除空值,但显然编译器无法识别它。

我可以通过将数组中的所有值转换为数字来解决这个问题,如下所示:

const values = [1, 2, null, 4]
    .filter(x => x)
    .map(x => x as number);

但我无法摆脱“必须有更好的方式”的感觉。

所以这是我的问题,有没有推荐/最佳实践方法来做到这一点?

1 个答案:

答案 0 :(得分:3)

你可以使用这样一个事实:filter有一个类似于此的过载,它适用于类型保护:

filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];

所以您需要做的就是将代码更改为:

class Test {
  constructor() {
    const isNotNull = <T>(x: T): x is NonNullable<T> => !!x;
    const values = [1, 2, null, 4].filter(isNotNull);
    this.printNumberArray(values);
  }

  printNumberArray(values: number[]) {
    console.log(values);
  }
}