typescript - 打字稿:对象键联合的类型不能用作该对象的键
问题描述
我有一个用一个参数调用的函数。这个参数是对象。此函数返回另一个对象,其中一个属性是传递给函数对象的值。当我尝试使用 obj[key] 表示法检索对象的值时遇到问题。
我确实理解,该密钥必须是正确的类型才能像这样使用。我不能使用简单的键作为字符串,如果在界面中我没有 [key: string]: any。但这不是问题。我的键是作为传递对象中键的字符串的联合:'user' | ‘名字’等
interface Twitter<T> {
name: T;
user: T;
sex: T extends string ? boolean : string;
}
interface Facebook<T> {
appName: T;
whatever: T;
imjustanexapmle: T;
}
type TwFbObjKeys = keyof Twitter<string> | keyof Facebook<string>
我的功能如下所示:
public static getArrayOfObjects(
queryParameters: Twitter<string> | Facebook<string>,
) {
const keys = Object.keys(queryParameters) as TwFbObjKeys[];
return keys.map((paramId) => ({
paramId,
value: queryParameters[paramId],
}));
}
我希望,使用 paramId 类型:'name' | '性' | '应用名称' | ...作为具有此键的对象的键,不会引发错误。但不幸的是我有错误:
TS7053:元素隐式具有“任何”类型,因为表达式类型为“名称”| '性' | '应用名称' | ... 不能用于索引类型 Twitter | Facebook。Twitter 类型上不存在属性“名称”| Facebook
我现在和它战斗了几个小时。知道我该如何解决吗?
解决方案
更好地将函数参数定义为具有约束的queryParameters
泛型类型,而不是联合类型:T
<T extends Twitter<string> | Facebook<string>>
Twitter<string> | Facebook<string>
function getArrayOfObjects<T extends Twitter<string> | Facebook<string>>(
queryParameters: T
) {
const keys = Object.keys(queryParameters) as (keyof T)[];
return keys.map((paramId) => ({
paramId,
value: queryParameters[paramId],
}));
}
解释
通过使用泛型,您可以保留传入参数的类型,queryParameters
并确保它是Twitter<string> | Facebook<string>
. paramId
with typekeyof T
现在可以访问queryParameters
属性。
使用联合类型Twitter<string> | Facebook<string>
,queryParameters
将保持未确定状态,并且可能在函数体中Twitter<string>
或Facebook<string>
在函数体中。在您的情况下,这会导致keyof
操作员和属性访问出现问题,因为您只能访问给定联合类型的所有成分的公共属性键。Twitter<string>
和没有共同的性质Facebook<string>
。
为了进一步说明这个问题,您可能打算定义TwFbObjKeys
为
// "name" | "user" | "sex" | "appName" | "whatever" | "imjustanexapmle"
type TwFbObjKeys = keyof Twitter<string> | keyof Facebook<string>
// not this: keyof only applies to Twitter<string> here: "name" | "user" | "sex" | Facebook<string>
type TwFbObjKeys_not = keyof Twitter<string> | Facebook<string>
但这并不能单独解决问题。例子:
declare const queryParameters: Twitter<string> | Facebook<string>
// type keysOfQueryParameters = never
type keysOfQueryParameters = keyof typeof queryParameters
// ok, let's try to define all union keys manually
type TwFbObjKeys = "name" | "user" | "sex" | "appName" | "whatever" | "imjustanexapmle"
declare const unionKeys: TwFbObjKeys
// error: doesn't work either
queryParameters[unionKeys]
// this would work, if both Twitter and Facebook have "common" prop
queryParameters["common"]
在泛型类型的帮助下,我们可以keyof T
安全地访问传入的queryParameters
键。
推荐阅读
- qtextdocument - 如何从 QTextDocument 中删除所有文本颜色属性?
- mysql - MYSQL 错误 1366, 1265 导入 200 万+ 行大 csv 文件时
- javascript - .mdx 文件中的流体图像
- uwp - 如何在不同主题的跳转开始列表和任务栏中显示不同的应用程序图标?
- javascript - 错误:无法读取未定义的属性推送
- c - 在C中获取范围内均匀分布的数字
- javascript - 如何将我的 App.vue 页面添加到 Vuex 商店?
- python-3.x - 一旦我们在 askopenfilename 中按下取消按钮,如何保留所选文件的路径
- react-native - 无法更改 Modal Reactnative 的状态
- database - 如何使用网络抓取工具在子页面上抓取电子邮件地址?