英文:
Using Type Predicates on a type that contains a Union type
问题
抱歉,您提供的代码片段中的英文部分已经翻译如下:
我定义了一些类型:
type Selected = {
ID: number
}
type DetailsV1 = {
Status: number
}
type DetailsV2 = {
Status: number,
Date: string
}
type DetailsDTO =
| DetailsV1
| DetailsV2
type SelectedDetails = DetailsDTO & Selected
我还定义了一个用户自定义的类型保护函数:
function detailsDTOIsV2(
details: DetailsDTO
): details is DetailsV2{
return (
(details as DetailsV2)
.Date !== undefined
)
}
当我有一个类型为 SelectedDetails
的对象时,如何访问 .Date
属性呢?
如果没有某种类型检查,我会得到 SelectedDetails
类型上不存在属性 Date
的错误。但是我看不到如何在 SelectedDetails
是一个交叉类型时检查类型,所以是否有其他方法可以解决这个问题?
英文:
Sorry for the weird title, super hard to word that
I have a few types defined:
type Selected = {
ID: number
}
type DetailsV1 = {
Status: number
}
type DetailsV2 = {
Status: number,
Date: string
}
type DetailsDTO =
| DetailsV1
| DetailsV2
type SelectedDetails = DetailsDTO & Selected
I also have a user defined type guard:
function detailsDTOIsV2(
details: DetailsDTO
): details is DetailsV2{
return (
(details as DetailsV2)
.Date !== undefined
)
}
When I have an object typed as SelectedDetails
how can I access the .Date
property?
Without some sort of type checking I get the Property Date does not exist on type SelectedDetails
. But I don't see how to check the types when SelectedDetails
is an intersection type, so is there another way to go about this?
答案1
得分: 1
你只需缩小到具有该属性的类型。在这种情况下,您可以使用 in
运算符来做到这一点。
selectedDetails.Date // 类型错误
if ('Date' in selectedDetails) {
selectedDetails.Date // 正常
}
这里的 'prop' in object
如果该属性存在于该对象上,将返回 true
。TypeScript会注意到这一点,并将您的联合类型缩小为只包含具有该属性的类型。
英文:
You simply have to narrow to the type that has that property. In this case you do that with the in
operator.
selectedDetails.Date // type error
if ('Date' in selectedDetails) {
selectedDetails.Date // fine
}
Here 'prop' in object
returns true
if that property is exists on that object. And TypeScript will notice this and narrow your union to just the ones that have property.
答案2
得分: 1
由于您已经拥有名为 detailsDTOIsV2
的 DetailsV2
类型守卫,您实际上可以将 SelectedDetails
传递给它,因为您的类型守卫期望一个 DetailsDTO
,而 SelectedDetails
是它的子类型。之所以允许这样的赋值是因为 TypeScript 的类型系统,它被称为结构类型系统,它只检查分配的值是否与分配的类型匹配,如果有一些未在类型中指定的额外字段,它不会触发错误。
只需将 selectedDetails
传递给类型守卫:
if(detailsDTOIsV2(selectedDetails)){
selectedDetails.Date //有效
}
或者,您可以使用 in
运算符也可以实现相同的结果:
if('Date' in selectedDetails) {
selectedDetails.Date // 有效
}
英文:
Since you already have a type-guard for the DetailsV2
named detailsDTOIsV2
, you can actually pass a SelectedDetails
to it, since your type-guard expects a DetailsDTO
and SelectedDetails
is a sub-type of it. The reason why such assignment is allowed is due to Typescript's type system, which is known as structural type system, that only checks if the assigned value matches the assigned type and doesn't fire an error if there are some extra fields that are not specified by the type.
Simply just pass the selectedDetails
to the type-guard:
if(detailsDTOIsV2(selectedDetails)){
selectedDetails.Date //works
}
Alternatively, you could use the in
operator that would achieve the same result:
if('Date' in selectedDetails) {
selectedDetails.Date // works
}
答案3
得分: 0
我认为这是无法绕过的。
TS编译器无法推断出SelectedDetails是否具有日期字段,除非有类型保护。
英文:
I think there is no way around this.
The TS Compiler cannot infer whether SelectedDetails will have Date field or no without type guard
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论