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和未定义的联合,因为这些是最常见的用例。
答案 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
,它可以一次性处理filter
和map
(这也不需要强制转换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[];
答案 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));
诀窍是传递一个 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)
为了避免每个人都一遍又一遍地编写相同类型的守卫助手函数,我将名为isPresent
,isDefined
和isFilled
的函数捆绑到一个助手库中: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[]
更长但更安全。
循序渐进:
typeof arrayWithNulls[number] // => string | null
null
值:NonNullable<typeof arrayWithNulls[number]> // => string
NonNullable<typeof arrayWithNulls[number]>[] // => string[]
链接:
NonNullable
(官方文档)typeof array[number]
(博客文章,我在官方文档上找不到任何相关信息)答案 13 :(得分:0)
您也可以使用双重否定 (!!) 来过滤掉所有 falsy 值:
array?.filter(item => !!item).map((item: any)