我试图通过使用Array.prototype.filter从数组中过滤null(undefined)元素,但TypeScript编译器似乎无法识别“过滤器”函数的派生数组并且未能通过类型检查 .
假设遵循简化代码,其中我有一个带有(number | undefined)[]类型的数组,并希望过滤undefined以适合number []数组 .
const arry = [1, 2, 3, 4, "5", 6];
const numArry: number[] = arry
.map((i) => {
return typeof i === "number" ? i : void 0;
})
.filter((i) => i);
错误说:
类型'(数字|未定义)[]'不能分配给'number []' . 输入'号码| undefined'不能分配给'number'类型 . 类型'undefined'不能分配给'number'类型 .
我可以将结果数组转换为数字[],如下所示,知道过滤器函数删除undefined .
const arry = [1, 2, 3, 4, "5", 6];
const numArry: number[] = (arry
.map((i) => {
return typeof i === "number" ? i : void 0;
})
.filter((i) => i) as Number[]);
除了铸造之外,还有更好的方法来实现这一目标吗?
环境:TSC2.1启用了strictNullChecks .
4 回答
Solution
创建一个类型守卫:
将它用作类型谓词:
Explanation
Array.prototype.filter
有一些重载 . 其中一个知道返回值将取决于您的谓词函数 . 它使用了一个类型后卫:使用适当的类型保护(而不是采用快捷方式并依赖于隐式强制)可以帮助TypeScript选择此特定的重载 .
使用TypeScrpt的用户定义类型保护功能:
在回调函数中查看
i is number
. 这个技巧使我们能够转换一种Array.filter结果 .使用内置的
filter
函数是不可能的,它被声明为返回一个与它接收的类型完全相同的数组 .但是,可以定义自己的,完全类型安全的过滤器函数,该函数接受数组和user-defined type guard function,并返回不同类型的数组 .
不确定有用,但这里是:
它可以像这样使用:
不幸的是,
isNumber()
必须被定义为单独的显式类型函数,因为编译器不够聪明,无法识别内联函数e => typeof e === 'number'
也是类型保护 .map(...)
函数签名是:在您的情况下,泛型类型
U
将是:number | undefined
filter(...)
签名是:由于
T
来自数组接口签名(Array<T>
),因此返回类型将是value
参数的相同类型的数组(泛型类型T
) . 在你的情况下number | undefined
.这就是你的返回类型是
number | undefined
的原因 .基于此,您将需要使用强制转换表达式 . 如果您不想要此行为,则可以删除
--strictNullChecks
标志 .