处理Typescript中嵌套的可能为null的值

时间:2018-09-13 07:50:58

标签: reactjs typescript graphql lodash apollo

我在使用Typescript的查询中使用GraphQL和自动生成的类型。它倾向于创建很多嵌套的type | null类型。因此,我需要对非null值进行相当长的检查。例如

            data &&
            data.getCoach &&
            data.getCoach.workouts &&
            data.getCoach.workouts.items &&
            data.getCoach.workouts.items.map((workout) => {/* do something*/});

我尝试使用lodash has助手来检查路径是否存在

has('getCoach.workouts.items', data) &&
data.getCoach.workouts.items.map((workout) => {/* do something*/});

但是ts编译器似乎不理解这一点。

除了让我的GraphQL端点始终返回值之外,还有更好的方法进行检查吗?

2 个答案:

答案 0 :(得分:1)

TypeScript的功能不足以表示您要执行的操作。理想情况下,JavaScript和TypeScript将具有null-coalescing operator,您将使用它。但是它没有那个。

如果尝试强力键入lodash has方法,则会发现编译器无法concatenate string literal types或执行regular expression operations on them,因此编译器无法采用字符串'getCoach.workouts.items'并了解getCoach将是data的键,而workouts将是data.getCoach的键,等等。

即使不使用has,表示此处涉及的嵌套类型操作也很棘手,而不会遇到recursion这样会使编译器生气或崩溃的问题。

我能做的最好的事情是:将对象包装在Proxy(需要ES2015或更高版本)中,该对象在您要使用的任何键上始终具有值,并且使用特殊的键名(例如{ {1}})提取属性的实际值,如果没有,则返回"value"。这是实现:

undefined

现在,代替这个:

type WrapProperties<T, K extends keyof any> = Record<K, T> & { [P in keyof T]-?: WrapProperties<T[P], K> }

function wrapProperties<T>(val: T): WrapProperties<T, "value">;
function wrapProperties<T, K extends keyof any>(val: T, valueProp: K): WrapProperties<T, K>;
function wrapProperties(val: any, valueProp: keyof any = "value"): WrapProperties<any, any> {
    return new Proxy({}, {
        get: (_, p) => p === valueProp ? val : wrapProperties(
            (typeof val === 'undefined') || (val === null) ? val : val[p], valueProp
        )
    });
}

您应该能够做到这一点:

if (data && data.getCoach && data.getCoach.workouts && data.getCoach.workouts.items) {
  data.getCoach.workouts.items.map((workout) => {/* do something*/}) 
}

我不知道实现是否完美。当我尝试它似乎工作。与从Stack Overflow获得的任何内容一样,您的里程可能会有所不同,并且需要注意。也许会对您有帮助。祝你好运!

答案 1 :(得分:0)

以为我刚才提到nullish coalescing已进入TC39的第二阶段!

我认为目前还没有任何灵巧的解决方案,因此,现在也许必须做类似jcalz的回答。

希望TS像他们对async / await所做的那样尽早引入它,我可以更新此答案。