如何对多层深度的对象强制执行空检查?

时间:2018-08-10 17:11:54

标签: javascript typescript redux-saga

我正在使用redux sagas通过一个公共接口从多个端点异步获取数据:

export interface ResponseInfo {
    data?: any;
    status: number;
    headers?: any;
    subCode?: string;
}

我想对数据对象(必须是任何类型)强制执行null检查,以便在其他开发人员尝试编写时

if(response.data.pizza.toppings){}

除非他或她添加了空检查,否则它将无法编译

if(response.data && response.data.pizza && response.data.pizza.toppings){

}

我们使用的是打字稿,但是--strictNullChecks在没有空检查的情况下不会标记以上行。这是no-unsafe-any在tslint中的用途吗?有没有办法让打字稿独自进行检查?

1 个答案:

答案 0 :(得分:1)

我们可以使用带有索引签名的接口定义这样的对象:

export interface ResponseInfo {
    data?: RecursiveObject;
    status: number;
    headers?: any;
    subCode?: string;
}

interface RecursiveObject {
    [s: string]: RecursiveObject | undefined
}

// Usage 

declare let response : ResponseInfo
if(response.data.pizza.toppings){ // Object is possibly 'undefined'

}

if(response.data.pizza){ // Object is possibly 'undefined'

}

一个问题是response.data.pizza.toppingsRecursiveObject,它不是很有用。为了解决这个问题(并且也更加安全),我们可以使用自定义类型防护将最终结果的类型缩小到有用的范围。 (请注意,常规类型的防护措施将不起作用,因为RecursiveObject与字符串无关,而像typeof response.data.pizza.toppings === 'string'这样的简单防护措施实际上会缩小到never

function isString(o: RecursiveObject|string ): o is string {
    return typeof o === "string"
}

declare let response : ResponseInfo
if(response.data && response.data.pizza && response.data.pizza.toppings
    && isString(response.data.pizza.toppings) ){
    let s : string = response.data.pizza.toppings;

}

有点冗长,但可能有用。