TypeScript过滤掉数组中的空值

时间:2017-03-30 13:02:40

标签: typescript

TypeScript, - strictNullChecks模式。

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

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

Array.filter在这里不起作用:

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

阵列理解可能有效,但TypeScript不支持它们。

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

14 个答案:

答案 0 :(得分:49)

您可以在AsEnumerable().CopyToDataTable()中使用type predicate功能,以避免选择退出严格类型检查:

.filter

或者,您可以使用function notEmpty<TValue>(value: TValue | null | undefined): value is TValue { return value !== null && value !== undefined; } const array: (string | null)[] = ['foo', 'bar', null, 'zoo', null]; const filteredArray: string[] = array.filter(notEmpty);

答案 1 :(得分:20)

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

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

答案 2 :(得分:18)

又一个很好的衡量标准,因为人们常常忘记flatMap,它可以一次性处理filtermap(这也不需要强制转换string[] ):

// (string | null)[]
const arr = ["a", null, "b", "c"];
// string[]
const stringsOnly = arr.flatMap(f => typeof f === "string" ? [f] : []);

答案 3 :(得分:10)

您可以将filter结果转换为所需类型:

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

这适用于您提到的更一般的用例,例如:

const array2: (string | number)[] = ["str1", 1, "str2", 2];
const onlyStrings = array2.filter(x => typeof x === "string") as string[];
const onlyNumbers = array2.filter(x => typeof x === "number") as number[];

code in playground

答案 4 :(得分:3)

这是一个我发现比@bijou-trouvaille 接受的答案更简洁的解决方案

const notEmpty = <T>(value: T): value is NonNullable<typeof value> => !!value 
const array: (string | null | undefined)[] = ['foo', 'bar', null, 'zoo', undefined];

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

答案 5 :(得分:2)

一个班轮:

const filteredArray: string[] = array.filter((s): s is string => Boolean(s));

TypeScript playground

诀窍是传递一个 type predicate:s is string 语法)。

This answer 显示 Array.filter 要求用户提供类型谓词。

答案 6 :(得分:1)

我认为这是一种简单的方法,代码更简洁

const array: (string | null)[] = ['foo', 'bar', null, 'zoo', null];
const filteredArray: string[] = array.filter(a => !!a);

答案 7 :(得分:1)

如果您已经使用Lodash,则可以使用"2020-12-15T13:00:00"。 或者,如果您更喜欢Ramda,则ramda辅助功能还具有UNTIL功能。

两者都有类型,因此您的tsc会很高兴并得到正确的类型。

从Lodash d.ts文件中:

recurrence[]

答案 8 :(得分:0)

我相信你一切都很好,只是类型检查只是使过滤后的类型与返回类型不同。

+----------+------------------------------------------------------+----------------------------------------------------------------+
| IS_VALID |                         COL                          |                          SHOW_ISSUES                           |
+----------+------------------------------------------------------+----------------------------------------------------------------+
|        1 | Symphony No. 4 in A Major, Op. 53: IV. Allegro molto | Symphony No. 4 in A Major, Op. 53: IV. Allegro molto           |
|        0 | Symphony No.4 in A Major, Op.53: IV. Allegro molto   | Symphony No<<<.>>>4 in A Major, Op<<<.>>>53: IV. Allegro molto |
+----------+------------------------------------------------------+----------------------------------------------------------------+

答案 9 :(得分:0)

为了避免每个人都一遍又一遍地编写相同类型的守卫助手函数,我将名为isPresentisDefinedisFilled的函数捆绑到一个助手库中:https://www.npmjs.com/package/ts-is-present

类型定义当前为:

export declare function isPresent<T>(t: T | undefined | null): t is T;
export declare function isDefined<T>(t: T | undefined): t is T;
export declare function isFilled<T>(t: T | null): t is T;

您可以这样使用:

import { isDefined } from 'ts-is-present';

type TestData = {
  data: string;
};

const results: Array<TestData | undefined> = [
  { data: 'hello' },
  undefined,
  { data: 'world' }
];

const definedResults: Array<TestData> = results.filter(isDefined);

console.log(definedResults);

当Typescript捆绑此功能时,我将删除该程序包。但是,暂时享受吧。

答案 10 :(得分:0)

如果您只是使用过滤器来检查其他条件是否为空,则可以使用此方法,希望这对某些正在寻找object array解决方案的人有所帮助

array.filter(x => x != null);
array.filter(x => (x != null) && (x.name == 'Tom'));

答案 11 :(得分:0)

只需使用

array.filter(Boolean);

这将适用于所有真值。

答案 12 :(得分:0)

TypeScript 有一些实用程序可以推断数组的类型并从中排除 null 值:

const arrayWithNulls = ["foo", "bar", null, "zoo", null]

type ArrayWithoutNulls = NonNullable<typeof arrayWithNulls[number]>[]

const arrayWithoutNulls = arrayWithNulls.filter(x => x != null) as ArrayWithoutNulls

比在新数组上手动投射 as string[] 更长但更安全。

循序渐进:

  1. 从原始数组中获取类型:
typeof arrayWithNulls[number] // => string | null
  1. 排除 null 值:
NonNullable<typeof arrayWithNulls[number]> // => string
  1. 使其成为一个数组:
NonNullable<typeof arrayWithNulls[number]>[] // => string[]

链接:

答案 13 :(得分:0)

您也可以使用双重否定 (!!) 来过滤掉所有 falsy 值:

  • 未定义
  • 空字符串"" ('')
  • 数字 0
  • 数字 NaN 例如,
    array?.filter(item => !!item).map((item: any)