首页 > 解决方案 > typescript 是否能够理解数组是否为非空并相应地推断某些数组方法的类型?

问题描述

我最近更新了 typescript 和 lodash,现在编译器明白,_.last()如果数组非空,例如方法将返回一个值,如果数组为空,则返回未定义。这是预期的行为,特别是如果我们不知道数组是否为空。

但是,在调用 等情况下_.last([1,2,3]),我们只知道数组是非空的,并且总是返回一个数字。此外,我在代码中有几个地方检查了非空,并采取了相应的行动,例如:

if (!_.isEmpty(array)) {
  return _.last(array);
}

...通过查看该代码,我们知道该语句将返回一个具有该数组中元素类型的元素。但是返回类型T | undefined仍然是。

我知道我可以在这种情况下转换价值。但我宁愿避免铸造东西。

所以我的问题是:打字稿有可能理解这样的情况吗?

标签: arraystypescriptlodash

解决方案


我们可以创建一个系统,isEmpty将信息添加到数组的类型中。这可以是我们可以称为HasElements<T>where Tcantrue或的类型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

推荐阅读