[英]How to check custom interface type in Typescript
我有
interface A {
a_id: string;
name: string;
}
interface B {
b_id: string;
name: string;
}
现在,我想检查一个对象说:
const myObj : A|B = {b_id: '1', name: 'one'};
如何检查类型并确定它属于A
还是B
?
我尝试了几个链接,但获取类型不应该更容易吗?
更新:所述问题并不表示请求能够在不检查属性的情况下区分类型。 不幸的是,这是不可能的。 TypeScript 编译为 JavaScript,这才是实际运行的内容。 而 TypeScript 的类型系统,在其中找到了A
和B
之类的接口,在编译代码时会被完全删除。 所以在运行时没有要检查的A
或B
如果您希望能够在运行时区分myObj
是A
还是B
,您需要编写执行此操作的 JavaScript 代码……例如检查属性。 您可以做的是使用 TypeScript 来帮助您编写此代码并为其指定类型,以便编译器也了解您的属性检查缩小了A | B
A | B
到A
或B
。 这就是这个答案的其余部分(以及另一个问题的答案)告诉你的。 祝你好运!
另一个问题的答案建议您编写一个用户定义的类型保护函数,它肯定会起作用; 这个想法是你告诉编译器你认为区分A
和B
的好方法,它会让你使用那个函数来做到这一点。
在您的情况下,一种更简单的方法是使用in
运算符,它可以用作类型保护(自 TypeScript 2.7 起)。 例如:
declare const obj: A | B;
if ("b_id" in obj) {
// obj is a B in here
console.log(obj.name.toUpperCase());
} else {
// obj is an A in here
console.log(obj.a_id.toUpperCase());
}
请注意,这在技术上是不安全的,因为可能有类型为A | B
的对象。 A | B
这种方式无法区分:
function getEvilAorB(): A | B {
interface EvilA extends A {
b_id: number;
}
const evilA: EvilA = { name: "", a_id: "", b_id: 123 };
return evilA; // okay, EvilA extends A extends A | B
}
注意getEvilAorB()
返回一个有效的A
,因此它是一个有效的A | B
A | B
,但不幸的是,由于数字name
属性,它将无法通过上述测试:
const evilA = getEvilAorB();
if ("b_id" in evilA) {
console.log(evilA.b_id.toUpperCase()); // compiles but 💥 at runtime
// TypeError! evilA.name.toUpperCase is not a function
}
如果您不关心此类边缘情况,那么in
类型保护可能就足够了。 否则,您应该考虑编写用户定义的类型保护,或者使您的接口成为可区分联合的成员,这是让编译器区分联合成员的传统且受支持的方式。
希望有所帮助; 祝你好运!
如果您能够改变这些接口的形状,对我来说是使用判别式的最简单方法。
interface A {
discriminantKey: 'interfaceA';
a_id: string;
b_id: string;
}
interface B {
discriminantKey: 'interfaceB';
b_id: string;
name: string;
}
并且当您在 swithc 情况下询问您的判别键时,即使在打字稿中,您也将拥有类型保护,而不仅仅是 runetime。
const myType = {...}
switch(myType.discriminantKey) {
case 'interfaceA':
// here is type infered to 'A' interface;
break
case 'interfaceB':
// here it is 'b'
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.