gpt4 book ai didi

javascript - 使用多种可选类型时出现 typescript 错误

转载 作者:行者123 更新时间:2023-12-04 12:27:43 25 4
gpt4 key购买 nike

这是一个错误示例:

interface Block {
id: string;
}

interface TitleBlock extends Block {
data: {
text: "hi",
icon: "hi-icon"
}
}

interface SubtitleBlock extends Block {
data: {
text: "goodbye",
}
}

interface CommentBlock extends Block {
author: string;
}

type BlockTypes = TitleBlock | SubtitleBlock | CommentBlock

function mapper(block : BlockTypes) {
if(block?.data?.text){ // TS Error here!!!
/** do something */
}
}
Live example
当 block 具有特定属性时,我想在函数中执行某些操作,但 TS 不允许我这样做,即使 BlockTypes 中有具有该属性的类型。
管理此类功能的最佳方法是什么?

最佳答案

optional chaining operator ( ?. )只防nullundefined ;它不过滤 union-typed向那些已知包含该 key 的成员表达。见 this comment in Microsoft/TypeScript#33736一个规范的答案。

问题是 TypeScript 中的对象类型是开放的,并且允许包含比编译器知道的更多的属性。所以如果 block.data是真实的,不幸的是,这并不意味着 block.data.text存在:

const oof = {
id: "x",
author: "weirdo",
data: 123
}
mapper(oof); // accepted
这里 oof是有效的 CommentBlock ,等等 mapper(oof)是允许的, oof.data是真的,但是 oof.data.textundefined ,如果你试图把它当作 string 来对待,你就会遇到问题。 .
因此,允许可选链接以您想要的方式过滤联合是不合理的(即不是类型安全的)。

这里的解决方法,如果您不认为 oof - 类似的情况很可能,是使用 the in operator as a type guard :
function mapper(block: BlockTypes) {
if ("data" in block) {
block.data.text.toUpperCase()
}
}
这工作正常,没有编译器错误。当然,与使用 ?. 收窄的方式完全相同,它仍然不可靠。会是……如果你调用 mapper(oof)没有编译器错误,但您会收到运行时错误。所以你应该小心。
TypeScript 允许 in 有点奇怪以这种方式行事,但不允许其他类似的构造。您可以阅读 microsoft/TypeScript#10485 中的讨论看看为什么会这样。大多数情况下,当人们写 "foo" in bar他们很少用它做错事,但其他结构如 bar.foo && bar.foo.baz更经常被滥用。但那是根据 TS 团队的说法,而不是我。 🤷‍♂️
Playground link to code

关于javascript - 使用多种可选类型时出现 typescript 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69302520/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com