我试图确保对象具有我期望它具有的所有键(.result.items
),唯一的问题是我得到以下错误:
Property result does not exist on type 'object'
日期:
typeof (object.result as Record<string, any>).items === "object"
我不理解这个错误,因为我似乎已经证明了object.result
确实存在于我的前一行中,并且它应该是object类型。
let objectKeyCheck = (
object: unknown
): object is { result: { items: object[] } } => {
return (
!!object &&
typeof object === "object" &&
!!(object as Record<string, any>).result &&
typeof (object as Record<string, any>).result === "object" &&
!!(object.result as Record<string, any>) &&
typeof (object.result as Record<string, any>).items === "object"
);
};
1条答案
按热度按时间xoefb8l81#
这里的问题是,当你在表达式上使用类型Assert时,它会“屏蔽”表达式,使其不受通常可能发生的任何narrowing的影响。例如:
在第一个块中,我们对
x
执行typeof
类型的保护,这允许我们将范围从string | number
缩小到仅string
;但是在第二个块中,我们没有保护x
,而是保护x as string
......这对x
没有任何影响。类型Assert和窄化不能真正混合使用。
为了解决这个问题,我会远离类型Assert,而只使用TypeScript 4.9中添加的支持,即使用
in
操作符对未列出的属性进行收缩:一旦我们把
object
从unknown
缩小到object
,然后检查"result" in object
,编译器会突然把object.result
当作一个有效的索引,属性类型从unknown
开始,然后我们可以把object.result
缩小到object
,对object.result.items
做同样的处理。请注意,上述内容依赖于TypeScript 4.9中添加的一个特性。如果您使用的是早期版本,几乎可以肯定还有其他方法也可以解决这个问题,但我不打算在这里离题探讨它们,因为它们已经过时,并且随着时间的推移将变得不那么有用。推荐的做法是升级TypeScript,对于那些需要针对特定旧版本的代码的人,我可能想问一个关于语言版本控制的新问题。
Playground代码链接