typescript - TypeScript:跨多种类型的接口?
问题描述
所以我从一个端点获取数据,该端点返回一个不同类型的集合,这些类型都具有相同的接口……类似于:
interface CommonInterface {
public type: string;
public commonProperty1: integer;
public commonProperty2: boolean;
}
class Thing1 implements CommonInterface {}
class Thing2 implements CommonInterface {}
然后端点返回CommonInterface[]
,它是Thing1
和Thing2
实例的混合。其中一个属性CommonInterface
是type
鉴别器,它识别它是哪个“事物”。
如何在 TypeScript 中对这种类型结构进行排序?如何告诉 TS 数组是 type CommonInterface
,然后告诉它第一项(基于type
值)是 a Thing1
,第二项是 a Thing2
,第三项是 a Thing1
?
我已经进行了一些搜索,但没有找到任何真正理解这种情况的东西。在此先感谢您的帮助!
解决方案
假设您获得了以下类定义:
class Thing1 implements CommonInterface {
readonly type = "Thing1";
commonProperty1 = 1;
commonProperty2 = true;
thing1Prop = "okay";
}
class Thing2 implements CommonInterface {
readonly type = "Thing2";
commonProperty1 = 2;
commonProperty2 = false;
thing2Prop = "okay";
}
我倾向于构建用户定义的类型保护函数来表示测试以查看 aCommonInterface
是 aThing1
还是 aThing2
或其他东西。它可能看起来像这样:
type Things = Thing1 | Thing2;
function isThing<T extends Things["type"]>(
obj: CommonInterface, type: T
): obj is Extract<Things, { type: T }> {
return obj.type === type;
}
你可能会像这样使用它:
function processCommonInterfaceArray(objs: CommonInterface[]) {
objs.forEach(c => {
if (isThing(c, "Thing1")) {
c.thing1Prop.toUpperCase();
} else if (isThing(c, "Thing2")) {
c.thing2Prop.toUpperCase();
} else {
// c is some other commonInterface
c.commonProperty1.toFixed();
}
})
}
从中可以看出,编译器使用isThing(c, "Thing1")
返回true
来得出c
必须是 a 的结论,Thing1
因此具有 a thing1Prop
。这同样适用于isThing(c, "Thing2")
和Thing2
。因为你不能确定所有CommonInterface
的对象都是肯定的Thing1
或Thing2
(没有什么能阻止某人拥有一个Thing3
that implements CommonInterface
),那么你需要在最后一个else
子句中做一些事情。
请注意,通常我希望您使用类型的可区分联合之类的东西Things
而完全忘记CommonInterface
。如果您可以重构您的类型以使端点返回Things[]
而不是CommonInterface[]
,那么您不需要用户定义的类型保护来进行控制流缩小:
function processThings(objs: Things[]) {
objs.forEach(c => {
if (c.type === "Thing1") {
c.thing1Prop.toUpperCase();
} else {
c.thing2Prop.toUpperCase();
}
})
}
好的,希望有帮助;祝你好运!
推荐阅读
- dart - CircularProgressIndicator 不显示在颤振中
- php - 未在 eBay 重定向 URL 上获得响应代码
- reactjs - 重置redux-form时react-select不清除值
- android - sqlite数据库中的图像索引
- php - Laravel 方法 Illuminate\Mail\Mailer::test 不存在
- c++ - 对类型的非 const 左值引用 - 使用 Class 类型的参数时,Objective-C++ 包装器中的错误
- android - FB 在某些设备中不返回电子邮件(android chrome 组合)
- objective-c - 如何从字符串中获取电话号码?
- python - 使用 docker 时无法打开共享对象文件
- unix - 除了我在输出中提到的 evar 之外,我如何删除所有目录