TypeScript中如何为两个不同接口编写TypeGuard类型守卫?
解决TypeScript联合类型守卫的属性访问报错及多类型兼容问题
先修复当前代码的报错
你写的isA函数报错,是因为TypeScript对联合类型A | B有严格检查:只有属性在联合类型的所有成员中都存在时,才能直接访问。B类型没有foo属性,所以直接访问test.foo会触发错误。
可以用以下两种方式修复:
方式1:使用in操作符(推荐,类型安全)
通过in操作符检查属性是否存在,TypeScript会自动缩小类型范围:
interface A { foo: string } interface B { bar: string } function isA(test: A | B): test is A { return 'foo' in test; }
方式2:使用类型断言(临时解决,安全性稍弱)
如果确定检查逻辑可靠,可以用类型断言绕过TypeScript的检查:
function isA(test: A | B): test is A { return (test as A).foo !== undefined; }
兼容同时属于两种类型的对象的类型守卫
当然可以编写这类守卫。如果一个对象同时拥有foo和bar(即同时符合A和B的类型),只要它满足A的判定条件,isA就会返回true——因为TypeScript的类型守卫test is A的含义是“test可以赋值给A”,即便它同时也是B,这个判定依然有效。
如果需要精确区分「仅A」「仅B」「同时是A和B」三种情况,可以编写更细分的守卫:
// 辅助类型,标记“不包含某类型的属性” type Not<T> = { [K in keyof T]?: never }; // 判断是否仅为A(不同时是B) function isOnlyA(test: A | B): test is A & Not<B> { return 'foo' in test && !('bar' in test); } // 判断是否仅为B(不同时是A) function isOnlyB(test: A | B): test is B & Not<A> { return 'bar' in test && !('foo' in test); } // 判断是否同时是A和B function isBothAAndB(test: A | B): test is A & B { return 'foo' in test && 'bar' in test; }
内容的提问来源于stack exchange,提问作者Shiuyin
相关产品推荐
相关产品推荐

