微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将具有可选属性的强制类型转换为可索引类型

如何解决将具有可选属性的强制类型转换为可索引类型

在尝试将具有可选属性的类型作为可索引类型传递给类型脚本时,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'的参数不能分配给类型'{[键:字符串]:字符串|数; }'。属性“ thing1”与索引签名不兼容。输入'string | undefined'不能分配给'string |数'。类型'undefined'不能分配给类型'string |数字”。

当然,如果强制将参数的类型设置为可选,则该方法有效:

function processObject (obj: { [key: string]: string | number | undefined }): string {
    return "test"
}

我不明白为什么这样做是必要的。根据{{​​3}},可索引类型应该与具有相同隐式索引签名的其他类型兼容。

这些属性是否可选无关紧要-该属性应该根本不存在于对象上-对吗?为什么必须指定undefined?有没有更好的方法可以做到这一点?

解决方法

请考虑以下行将根据您对Thing的定义进行编译而不会发出警告:

const A: Thing = { thing2: undefined };

在调用processObject() 技术上正确时会导致错误;当您期望仅使用undefinedstring时,可能最终从对象读取number值。


说明:

TypeScript并不总是区分值(如对象属性或函数参数)缺失和值存在但undefined 的情况>。这种混淆是从JavaScript继承的,两者之间的差别可能很细微:如果我有一个名为obj的JavaScript对象,而obj.prop === undefinedtrue,我就无法确定{{1} }是对还是错。

GitHub microsoft/TypeScript#13195中存在一个长期未解决的问题,它要求在区分TypeScript中的"prop" in objundefined方面保持一致性。可选属性被视为“可能丢失”和“可能undefined”,反之,不允许 定义为必需的属性| undefined。现在无法说“我想要一个可能会丢失的财产,但如果存在的话,不应undefined”。

此外,index signatures还面临着相反的双重思考:实际上,您可以从中获得undefined的属性值(因为可能缺少任何给定的属性),但是编译器不承认这一点。 (并且行为就像存在并定义了每个可能的属性一样)。请参阅microsoft/TypeScript#13778,以获得有关在索引签名属性的域中自动包含undefined的建议,以及对此的不计其数的评论。即将出现的功能标志称为--noUncheckedIndexedAccess(请参见microsoft/TypeScript#39560),旨在解决此问题,但是即使将其打开,您的代码仍然会遇到相同的问题,因此无法完全解决在所有情况下都是如此。

在可选属性中处理缺失值和undefined值与在索引签名中如何处理缺失值之间的这种不匹配是导致问题的原因。


在我看来,解决此问题的方法只是将undefined添加到索引签名中,并明确承认可能存在可选属性,但undefined除外。这不是理想的方法,但至少更接近一致。


Playground link to code

,

由于此更改,这不再在 TypeScript 4.2 中重现:https://devblogs.microsoft.com/typescript/announcing-typescript-4-2-rc/#relaxed-rules-between-optional-properties-and-string-index-signatures (https://github.com/microsoft/TypeScript/pull/41921)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。