TypeScript类型守卫的几种方式

typeof 以及 instanceof

使用 typeof 以及 instanceof 关键词判断的方式也可以收敛类型。

function strOrNum(input: string | number) {
  if (typeof input === 'string') {
    // input is string now
  } else {
    // input is number
  }
}

真值法(Truthiness)和判等法(equality)

declare const obj: Record<string, unknown> | null;
declare const bool1: boolean | undefined;
declare const bool2: boolean | null;

// if (obj) 那 obj 肯定不是 null 了
if (obj) {
  // obj: Record<string, unknown>
} else {
  // obj: null
}

// if (bool1 === bool2) 那 bool1 不可能是 undefined,因为 undefined 类型的变量永远不会等于 boolean,也永远不会等于 null;同样地,bool2 只能是 boolean
if (bool1 === bool2) {
  // bool1: boolean
  // bool2: boolean
}

in

in 判断某属性或者方法是否在对象中

type Fish = { swim: () => void };
type Bird = { fly: () => void };

function move(animal: Fish | Bird) {
  if ('swim' in animal) {
    return animal.swim();
  }

  return animal.fly();
}

as

as 直接告诉 typescript 某对象是什么类型

declare const str: any;
let res = (str as string).toUpperCase();

declare const num: number;
let res2 = (num as unknown as string).toLowerCase();
// 不能直接收敛的情况下,要先断言为更宽泛的类型,如 unknown

自定义类型守卫函数

可以通过自己实现类型守卫函数来将类型收敛性。类型守卫比 typeof 更加强大了。

type Fish = { swim: () => void };
type Bird = { fly: () => void };
declare function getSmallPet(): Fish | Bird;

// 自定义类型守卫函数
function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

let pet = getSmallPet();

if (isFish(pet)) {
  // pet类型被收敛到了类型 Fish 上
  pet.swim();
} else {
  pet.fly();
}

断言函数 assert functions

断言函数:如果类型不符合所预期的,会报错

Node.js 有一个专门的断言函数assert

function multiply(x: any, y: any) {
  assert(typeof x === 'number');
  assert(typeof y === 'number');

  // both x and y is number now
  return x * y;
}

也可以自定义实现 assert 函数

法一

function myAssert(param: any, msg?: string): asserts param {
  if (!param) {
    throw new Error(msg);
  }
}

function multiply(x: any, y: any) {
  myAssert(typeof x === 'number');
  myAssert(typeof y === 'number');
  // both x and y is number now
  return x * y;
}

法二

declare function isOdd(param: unknown): asserts param is 1 | 3 | 5;
function num(input: number) {
  isOdd(input);
  console.log(input);
  // input is 1 | 3 | 5
}

! 后缀

! 可以从排除掉 null 和 undefined

declare const obj: { name: string } | null;
const name = obj!.name; // obj被断言为了 {name: string}

考虑到 type 安全,尽量不要用这个标识符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值