arrays - typescript 是否能够理解数组是否为非空并相应地推断某些数组方法的类型?
问题描述
我最近更新了 typescript 和 lodash,现在编译器明白,_.last()
如果数组非空,例如方法将返回一个值,如果数组为空,则返回未定义。这是预期的行为,特别是如果我们不知道数组是否为空。
但是,在调用 等情况下_.last([1,2,3])
,我们只知道数组是非空的,并且总是返回一个数字。此外,我在代码中有几个地方检查了非空,并采取了相应的行动,例如:
if (!_.isEmpty(array)) {
return _.last(array);
}
...通过查看该代码,我们知道该语句将返回一个具有该数组中元素类型的元素。但是返回类型T | undefined
仍然是。
我知道我可以在这种情况下转换价值。但我宁愿避免铸造东西。
所以我的问题是:打字稿有可能理解这样的情况吗?
解决方案
我们可以创建一个系统,isEmpty
将信息添加到数组的类型中。这可以是我们可以称为HasElements<T>
where T
cantrue
或的类型false
。如果该类型仍未经测试,则它的类型 ( T[] & (HasElements<true> | HasElements<false>)
) 应该具有两种可能性。不幸的是,这必须手动添加到类型中。
import _ from 'lodash'
declare module 'lodash' {
type HasElements<T extends boolean> = T extends boolean ? { // distributive conditional, makes HasElements<boolean> == HasElements<true> | HasElements<false>
"gurad-traits"?: {
hasElements?: T
}
}: never
interface LoDashStatic {
isEmpty<T extends HasElements<boolean>>(value?: T): value is T & HasElements<false>;
last<T> (array: List<T> & HasElements<true>): T;
last<T> (array: (List<T> & HasElements<false> )| null | undefined): undefined;
}
}
function test<T>(array: T[] & _.HasElements<boolean>, defaultValue: T): T {
if (!_.isEmpty(array)) {
return _.last(array);
}else {
let u: T = _.last(array); /// err, returns undefined
return defaultValue;
}
}
test([1,2,3], 1); //HasElements does not influence the assignability of arrays