typescript - 为什么 Typescript 将 `object.hasOwnProperty("key")` 视为与 `"key" in object` 本质上不同
问题描述
declare const action: { total: number } | { };
declare const defavlt: 200;
const total = (action.hasOwnProperty("total")) ? action.total : defavlt;
导致以下 TS 错误action.total
:
Property 'total' does not exist on type '{ type: "NEW_CONVERSATION_LIST" | "UPDATE_CONVERSATION_LIST_ADD_BOTTOM" | "UPDATE_CONVERSATION_LIST_ADD_TOP"; list: IDRArray<RestConversationMember>; total: number | undefined; } | ... 13 more ... | { ...; }'.
Property 'total' does not exist on type '{ type: "UPDATE_URL_STATE"; updateObj: IMessagingUrlState; }'.ts(2339)
然而
const total = ("total" in action) ? action.total : defavlt
作品。TS 是否有理由以不同的方式对待这两种情况?
解决方案
在问题microsoft/TypeScript#10485中,建议in
操作员充当可用于过滤联合的类型保护;这是在microsoft/TypeScript#15256中实现的, 并与 TypeScript 2.7 一起发布。
这不是为Object.prototype.hasOwnProperty()
; 如果你真的对此有强烈的感觉,你可能想提出一个建议,注意到一个类似的建议 (microsoft/TypeScript#18282)被拒绝了,因为它要求的是更有争议的缩小键而不是对象.. . 有些人两者都想要 (microsoft/TypeScript#20363)。并且不能保证该建议会被接受。
不过,幸运的是,您不必等待它在上游实施。与类似 的运算符不同in
,该hasProperty()
方法只是一个库签名,可以更改为充当用户定义的类型保护函数。更重要的是,您甚至不必接触标准库的定义;您可以使用声明合并Object
来使用您自己的签名来扩充接口hasOwnProperty()
:
// declare global { // need this declaration if in a module
interface Object {
hasOwnProperty<K extends PropertyKey>(key: K): this is Record<K, unknown>;
}
// } // need this declaration if in a module
该定义表明,当您检查 时obj.hasOwnProperty("someLiteralKey")
,true
结果意味着obj
可分配给{someLiteralKey: unknown}
,而false
结果则不能。这个定义可能并不完美,并且可能有很多边缘情况(例如,应该obj.hasOwnProperty(Math.random()<0.5?"foo":"bar")
暗示什么?应该obj.hasOwnProperty("foo"+"bar")
暗示什么?他们会做奇怪的事情)但它适用于您的示例:
const totalIn = ("total" in action) ? action.total : defavlt; // okay
const totalOwnProp = (action.hasOwnProperty("total")) ? action.total : defavlt; // okay
好的,希望有帮助;祝你好运!
推荐阅读
- python - (Django)如何让用户 FK 注册用户名而不是代码(int)
- python - h5py 无法读取 julia HDF5 编写的字符串
- java - 请求范围 bean 的 bean 创建错误
- javascript - 我如何将此 JavaScript 代码转换为 Python 代码?
- javascript - 如何绑定:样式与对象语法和多个背景图像?
- npm - 为什么 Sonatype Nexus 以 405 错误响应“npm login”?
- python - 不显示模板中浏览次数最多的文章列表
- exiftool - 解决“没有设置可写标签”错误
- jquery - 如何使用可搜索下拉列表的 json 结果获取数据?
- perl - 安装 Perl 模块失败时查看 Bitbucket 管道中的 cpanm 错误日志