TypeScript Optional Chain

假如接口有如下返回

const response = {
  code: 0,
  data: {
    name: 'leevare',
    age: 20,
    address: {
      province: '上海',
      city: '闵行区',
    },
  },
};

如果想获取省份的值,通常是使用response.data.address.province,但是由于接口的不确定因素,可能最终返回的数据data可能是一个空,那么这时候肯定会报错。解决的方式很简单,可以使用短路的方式。

response && response.data && response.data.address && response.data.address.city;

或者使用三目运算符

response
  ? response.data
    ? response.data.address
      ? response.data.address.city
      : undefined
    : undefined
  : undefined;

带来的问题也显而易见,代码变得复杂了。

在ts中,提供一种可选链的方式解决这个问题,使用?.

使用可选链,上面的代码可以转变为response?.data?.address?.city;,不确定的属性使用?.访问,代码最终编译为

(_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.address) === null || _b === void 0 ? void 0 : _b.city;

它首先判断了属性是不是为nullundefined,然后再对其属性进行访问。

?. 与 && 的区别

所以,我都使用?.代替&&可以吗?

其实不一定,使用?.的时候,ts只是检查属性是不是为nullundefined,但是对于其他的falsy值,并没有做检测,例如0,false等,就意味着,当为这些falsy值的时候,并不会出现短路的效果,从而出现错误。

如果使用&&操作符,它会对falsy值进行短路运算,则不会出现问题。

所以,使用可选链的时候还是需要慎重。

可选链与函数搭配

依然是使用?.的形式。

type Person = {
  a: {
    b?: {
      c?: {
        d?: () => void;
      };
    };
  };
};

let p: Person;

p.a.b?.c?.d?.()

其最终编译为

var p;
(_e = (_d = (_c = p.a.b) === null || _c === void 0 ? void 0 : _c.c) === null || _d === void 0 ? void 0 : _d.d) === null || _e === void 0 ? void 0 : _e.call(_d);

与函数搭配的时候使用时需要注意。

1、如果存在一个属性名且该属性名对应的值不是函数类型,使用?.仍然会产生一个TypeError异常。

2、可选链的运算行为被局限在属性的访问、调用以及元素的访问 —— 它不会沿伸到后续的表达式中,也就是说可选调用不会阻止a?.b / someMethod()表达式中的除法运算或someMethod的方法调用。

访问可选元素

const arr = [1, 2, 3];
console.log(arr?.[0]);

最终编译为

var arr = [1, 2, 3];
console.log(arr === null || arr === void 0 ? void 0 : arr[0]);
如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注