TS如何解决属性在另一个类型中不存在的问题?

先来看一个例子:

export interface Cat {
  coatColor: string; // 毛色
  varieties: string; // 品种
  weight: number; // 体重
  meow: () => void; // 喵喵叫
}
export interface Dog {
  coatColor: string;
  varieties: string;
  weight: number;
  bark: () => void; // 汪汪叫
}

const getAnimalInfo = isCat ? getCatInfo : getDogInfo;
const animal = await getAnimalInfo<Cat | Dog>({name: 'kangshifu'});

let call;
if(isCat){
  call = animal.meow; 
  /* 报错,提示:
	类型“Cat | Dog”上不存在属性“meow”。
	类型“Dog”上不存在属性“meow”。
  */
} else {
  call = animal.bark;
  /* 报错,提示:
	类型“Cat | Dog”上不存在属性“bark”。
	类型“Cat”上不存在属性“bark”。
  */
}

该 Demo 由真实案例改编而来

现在我们假设,只能用一个变量来保存可能来自两个不同接口返回的数据,接口返回值类型已经设定为或的关系。

从变量中取某一个类型特有的属性时,便会提示在另一个类型中不存在该属性,应该如何解决?

目前个人已知有三种常用解决方案

1. 在变量取值时进行断言

let call;
if(isCat){
  call = (animal as Cat).meow; 
} else {
  call = (animal as Dog).bark;
}

当 Cat 或 Dog 特有属性较多时,就需要加非常多的断言,会使代码显得十分不优雅

2. 借助类型守卫

什么是类型守卫?

TS 在遇到以下这些条件语句时,会在语句的块级作用域内「收紧」变量的类型,这种类型推断的行为称作类型守卫 (Type Guard)。

  • 类型判断:typeof
  • 实例判断:instanceof
  • 属性判断:in
  • 字面量相等判断:=====!=!==

(这里列举常用的 4 种)
类型守卫可以帮助我们在块级作用域中获得更为精确的变量类型

这里就可以通过判断 animal 中是否存在 meow 属性,来确定变量是否为 Cat 类型的对象

let call;
if(isCat && 'meow' in animal){
  call = animal.meow; // 鼠标放到 animal 上,可以看到类型被限定为 Cat
} else if(!isCat && 'bark' in animal) {
  call = animal.bark; // animal 类型被限定为 Dog
}

个人并不是很推荐这种方式

真实的开发中,Cat 的特有属性往往有很多,不论使用哪个属性,似乎都在表示我们尝试以偏概全,至少代码看起来是这样的,就会显得十分不优雅

但不得不承认这也是一种非常好的限定类型的方法

‘meow’ 的值是 null 或 undefined 都会不影响 in 的判断,只要存在该属性均会返回 true

3. 将老变量赋值给被限定类型的新变量

let call;
if(isCat){
  const cat: Cat = animal;
  call = cat.meow;
} else {
  const dog: Dog = animal;
  call = dog.bark;
}

个人比较推荐第三种,大家也可以发表一下各自的看法,集思广益

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麦田里的POLO桔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值