我想提取一个narrow类型的结果类型,我有一个Parent
类型,它有一个x
属性,而x
属性又有两个a
和b
属性,其中至少有一个必须被设置,我用联合体对此建模:
type A = {
type: "A",
a: string
}
type B = {
type: "B",
b: string
}
type AB = {
type: "AB",
a: string
b: string
}
type Parent = {
x: A | B | AB
// potentially many more properties
}
const ps : Parent[] = []
使用类型鉴别器可以很好地进行类型收缩。
ps.map(p => {
if(p.x.type == "AB") {
p.x.a // works!
}
})
在我的代码的某些地方,我只处理同时具有a
和b
属性的父对象,例如,通过使用过滤器。
const asAndBs = ps.filter((p) : p is AAndBParent => p.x.type == "AB")
为此,我需要有一个显式引用到缩小类型AAndBParent
,它将被定义为类型Parent
,其中Parent.x.type == "AB"
.我能想到的唯一方法是"从头开始"创建一个新类型.这是繁琐的,如果父有很多属性,这将不得不在类型定义之间同步.
type AAndBParent = {
x: AB
// would have to copy all other properties from Parent
}
- 问题1**:可以相对于父对象定义
AAndBPanret
吗?
- 问题1**:可以相对于父对象定义
- 问题2**:我可以用类型安全的方式定义过滤函数吗?
我可能写错了类型 predicate ,但编译器不会抱怨,编译器的类型收缩逻辑知道得更清楚。
const asAndBs = ps.filter((p) : p is AAndBParent => p.x.type != "AB")
asAndBs[0].x.a // runtime error: potentially undefined
1条答案
按热度按时间yc0p9oo01#
我可以定义与
Parent
相关的AAndBParent
吗?是-要从现有类型派生新类型并同时缩小一个或多个属性,可以使用与具有缩小属性的类型的交集,如下所示:
TSPlayground
我可以用类型安全的方式定义过滤函数吗?
好耶!
然而,创建类型保护函数可能需要一些技巧--它们的存在是为了让您在内置控制流分析实际上无法提供您所期望的收缩的地方帮助编译器--它们在概念上与类型Assert相关,因为它们是让您提供比编译器更多信息的机制。
TypeScript可以防止你犯这样的明显错误:
但是您要负责确保在函数体中执行的运行时验证与 predicate 中的类型一致。
在您的例子中,您只是验证对象的形状是否为
{ x: { type: "AB" } }
,因此只需在 predicate 中使用它,并让编译器推断其余部分-它将按预期工作:TSPlayground代码