typescript - 将具有可选属性的类型强制为可索引类型
问题描述
尝试将具有可选属性的类型作为可索引类型传递时,Typescript 会引发错误:(Playground)
type Thing = {
thing1?: string
thing2?: string
thing3?: number
}
const thing: Thing = {}
function processObject (obj: { [key: string]: string | number }): string {
/* Generic object handler, not specifically for Thing */
return "test"
}
console.assert(processObject(thing) === "test")
这导致:
错误:'Thing' 类型的参数不能分配给'{ [key: string] 类型的参数:string | 数字; }'。属性“thing1”与索引签名不兼容。键入'字符串 | undefined' 不可分配给类型 'string | 数字'。类型 'undefined' 不能分配给类型 'string | 数字'。
当然,如果参数的类型被强制设为可选,它会起作用:
function processObject (obj: { [key: string]: string | number | undefined }): string {
return "test"
}
不过,我不明白为什么这是必要的。根据TS PR #7029,可索引类型应该与具有相同隐式索引签名的其他类型兼容。
这些属性是否是可选的无关紧要-该属性根本不应该出现在对象上-对吗?为什么我必须指定undefined
?有没有更好的方法来做到这一点?
解决方案
考虑到根据您的定义,以下行将在没有警告的情况下编译Thing
:
const A: Thing = { thing2: undefined };
这在processObject()
技术上正确调用时会出错;当您只期望 a或 a时,您最终可能会undefined
从对象中读取一个值。string
number
解释:
TypeScript 并不总是将缺少值(如对象属性或函数参数)的情况与存在值但undefined
. 这种混淆是从 JavaScript 继承而来的,其中的区别可能很微妙:如果我有一个名为obj
, 和obj.prop === undefined
is的 JavaScript 对象true
,我无法从中判断"prop" in obj
是真还是假。
GitHub 中有一个长期未解决的问题microsoft/TypeScript#13195,要求在区分“缺失”和undefined
TypeScript 方面保持一致。可选属性被视为“可能丢失”和“可能undefined
”,而相反,不允许丢失定义中的必需属性| undefined
。现在没有办法说“我想要一个可能丢失的属性,但如果它存在,它不应该存在”。undefined
此外,索引签名也受到相反方向的双重思考:实际上,您可以从中获取undefined
属性值(因为可能缺少任何给定的属性)但编译器不承认这一点(并且表现得好像每个可能的属性都存在并定义)。请参阅microsoft/TypeScript#13778以了解undefined
自动包含在索引签名属性域中的建议,以及有关它的无数评论。有一个即将推出的名为--noUncheckedIndexedAccess
(参见microsoft/TypeScript#39560)的功能标志旨在解决此问题,但即使您打开它,您的代码仍然会遇到同样的问题,因此它并不能在所有情况下都完全修复它。
undefined
在可选属性中处理缺失值和值的方式与在索引签名中处理它们的方式之间的这种不匹配是导致问题的原因。
在我看来,处理这个问题的方法就是将它添加undefined
到您的索引签名中,并明确承认可能存在可选属性,但是undefined
. 这并不理想,但至少更接近于一致。
推荐阅读
- javascript - jQuery中无法识别的表达式
- r - 在 R Shiny 中,如何在 renderUI 部分嵌入一个 observeEvent 函数?
- intersection - 使用 CGAL 的两个多面体相交的体积
- python - ansible 命令仅使用绝对路径运行
- html - 在html模板中编写表单媒体后,我无法上传所有内容
- java - 出现错误:尝试在空对象引用上调用虚拟方法“android.text.Editable android.widget.EditText.getText()”
- git - 是否可以为 Gerrit 中的每次提交都设置主题?
- django - Django 未使用更新的 urls.py - 在 www.site.com/page 上返回 404,列表已过时
- javascript - 获取响应问题
- node.js - NodeJS Express Web 应用程序的一次性密码验证