gpt4 book ai didi

typescript - 为什么泛型字典类型不返回可能未定义的值?

转载 作者:行者123 更新时间:2023-12-04 13:57:59 26 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Trying to understand index signatures in TypeScript

(2 个回答)


2年前关闭。




使用 Typescript 遇到了一些非常出乎意料的事情

我一直在使用以下模式来指定对象是 string 的字典Foo 的 key 值(value)观
type Dictionary = { [id: string]: Foo }
真正奇怪的是,当我尝试使用任何键从字典中检索值时,Typescript 将返回类型提供为 Foo
我希望它是 Foo | undefined ,当然如果键没有映射到任何值,undefined被退回。

这是为什么会出现意外行为的示例 - see the playground here

type Foo = { bar: number }
type Dictionary = { [id: string]: Foo }

const a: Dictionary = {
one: { bar: 1 },
two: { bar: 2 }
}

const addOneToBar = (foo: Foo) => foo.bar + 1

// No type error, maybe expected, because we 'know' from context that
// the one property exists on the Dictionary instance a
alert(addOneToBar(a.one))
alert(addOneToBar(a['one']))

try {
// There is still no type error here, though. Why?
// Shouldn't a.three / a['three'] return Foo | undefined
// instead of Foo, because we're not certain there is any three property?
alert(addOneToBar(a.three))
alert(addOneToBar(a['three']))
} catch (err) {
alert('Of course, there is a null pointer error: ' + err)
}

这段代码在我看来显然不是类型安全的,并且确实导致了一个没有被 Typescript 标记的运行时异常。

我真的对此感到惊讶 - 返回 undefined对于指向空的键是 Javascript 对象的基本行为,我猜大多数语言中的任何通用字典/ map 实现。我不明白为什么 Typescript 会错过这个。

也许我在上面的代码中犯了一个错误,或者我误解了 { [id: string]: Foo } 的目的模式,和/或在 Typescript 中输入字典的另一种模式确实具有我应该使用的这种行为(我已经尝试过 Record 类型,再次令我惊讶的是,它也表现出相同的行为)。

这里发生了什么?

编辑

我刚刚意识到写下我可能可以做的问题 type Dictionary = { [id: string]: Foo | undefined }得到这种行为。但同样,为什么这不是开箱即用的默认设置?也许如果你有一个窄键类型,比如枚举,它会有意义,但如果你有一个 string key 保证总是从字典中返回一个值是绝对错误的,不是吗?

进一步编辑

在评论中,我现在意识到 Typescript 的这种行为实际上是有道理的,上面的解决方案是 明确告诉 TS 字典可能返回未定义的值是解决方案。从某种意义上说,这是我假设 TS 应该从类型推断事物而不是我必须明确说明它们 - 你可以以任何一种方式争论便利情况 - 我提出的它应该表现的方式对于可能丢失键的情况是好的,但是当你确定他们不会的时候不好。 TS 在这里的实际行为方式恰恰相反。

模组

这不是一个本身有答案的问题(TypeScript 只是按设计工作),但我会保留它,除非它获得接近投票,因为我认为这是对行为的有趣总结以及为什么要实现就这样。

最佳答案

通过声明 type Dictionary = { [id: string]: Foo } ,您告诉编译器任何字符串都是此类型的有效键。然后编译器不会假设哪些字符串是有效键,哪些不是,本质上是说定义了任何属性访问器并将返回 Foo .

如果你想强制执行,只有 onetwo为您的对象定义了键,然后您可以严格定义字典的属性:

type Dictionary = {
one: Foo;
two: Foo;
}

关于 typescript - 为什么泛型字典类型不返回可能未定义的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57497126/

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