TypeScript,——strictNullChecks模式。

假设我有一个可空字符串数组(string | null)[]。什么是单表达式的方式,以这样的方式删除所有的空值,结果有类型字符串[]?

const array: (string | null)[] = ["foo", "bar", null, "zoo", null];
const filterdArray: string[] = ???;

数组中。过滤器在这里不起作用:

// Type '(string | null)[]' is not assignable to type 'string[]'
array.filter(x => x != null);

数组推导式可以工作,但TypeScript不支持。

实际上,这个问题可以推广为通过从联合中删除具有特定类型的项来过滤任何联合类型的数组的问题。但是让我们关注带有null和可能未定义的联合,因为这些是最常见的用例。


当前回答

如果您可以接受另一个.map()的开销,一个优雅的解决方案是使用非空断言操作符。

const array = ["foo", "bar", null, "zoo", null];
const filterdArray: string[] = array.filter(s => s != null).map(s => s!);

如果你想保留未定义,你可以在变量上使用typeof,并使用实用程序类型Exclude来从类型中删除空值。

const array = ["foo", "bar", null, "zoo", null];
const filterdArray: string[] = array
  .filter(s => s !== null)
  .map(s => s as Exclude<typeof s, null>);

其他回答

类似于@ bijouu -trouvaille的回答,你只需要声明<arg> is <Type>作为过滤器函数的输出:

array.filter((x): x is MyType => x !== null);

下面是一个使用NonNullable的解决方案。我发现它甚至比@ bijouu -trouvaille的公认答案更简洁

function notEmpty<TValue>(value: TValue): value is NonNullable<TValue> {
    return value !== null && value !== undefined;
}
const array: (string | null | undefined)[] = ['foo', 'bar', null, 'zoo', undefined];

const filteredArray: string[] = array.filter(notEmpty);
console.log(filteredArray)
[LOG]: ["foo", "bar", "zoo"]

使用减少

一些答案建议减少,下面是如何减少的:

const languages = ["fr", "en", undefined, null, "", "de"]

// the one I prefer:
languages.reduce<string[]>((previous, current) => current ? [...previous, current] : previous, [])

// or
languages.reduce((previous, current) => current ? [...previous, current] : previous, Array<string>())

// or
const reducer = (previous: string[], current: string | undefined | null) => current ? [...previous, current] : previous
languages.reduce(reducer, [])

结果:(“fr”、“en”、“de”)

这里是TS游乐场。

如果你使用过滤器检查null和其他条件,这可以简单地使用,希望这有助于寻找对象数组的解决方案的人

array.filter(x => x != null);
array.filter(x => (x != null) && (x.name == 'Tom'));
const filterdArray = array.filter(f => !!f) as string[];