javascript - TypeScript:具有已知键的对象上的 Object.keys() 类型过于通用
问题描述
我正在学习 TypeScript,我很难理解的一件事是如何正确迭代对象的键。一个非常常见的应用程序是这样的:
type T = {
"a": number,
"b": number
}
const obj : T = {
a: 1,
b: 2
};
const keys = Object.keys(obj);
const m = keys.map(k => 2*obj[k]);
我有一个obj
已知类型的对象,T
并希望获取所有键来调用map
它们。的返回类型Object.keys([type T])
根据string[]
Visual Studio Code。我在别处读到,这样做的原因是传递给的对象Object.keys
可能是T
. 但是,在此示例中,很明显该对象具有类型T
而不是子类型(具有更多键)。
由于返回类型过于笼统,TS 编译器在使用键map
读取每个键的实际值时向我显示错误。这是有道理的,因为只允许“a”和“b”,但编译器认为任何其他字符串也可能出现(这是错误的,至少在这个例子中)
调用map
对象键的推荐方法是什么?使用此方法强制转换类型有效:
function getKeysGen<T extends object>(o: T) {
return Object.keys(o) as Array<keyof T>;
}
const keys = getKeysGen(obj); // correctly shown as Type ("a" | "b")
调用通用键获取器时我什至不必指定类型,TS/VSCode 似乎能够从参数本身的类型中推断出来。但是为什么这不适用于原始Object.keys
功能?
为什么这不起作用?
function getKeys(o: Object) {
return Object.keys(o) as Array<keyof typeof o>;
}
const keys = getKeys(obj); // VSCode shows the type is ("constructor" | "toString" | "toLocaleString" | "valueOf" | "hasOwnProperty" | "isPrototypeOf" | "propertyIsEnumerable")[]
当我运行此代码时,keys
实际上包含[ 'a', 'b' ]
而不是 VSCode 显示给我的键。但是,当使用键将值映射到它们的双精度时,TS 编译器会拒绝:
const m = keys.map(k => 2*obj[k]);
错误是
错误 TS2363:算术运算的右侧必须是“any”、“number”、“bigint”类型或枚举类型。
很可能是因为k
没有正确推断出的类型,所以2*undefined
可能会发生类似的事情。
我在上面写的通用函数getKeysGen
是要走的路还是有什么我遗漏的地方?
解决方案
Object.keys
对于您要查找的内容,类型定义确实太笼统了。如果您查看lib.es2015.cor.d.ts
,您会看到:
keys(o: {}): string[];
string[]
不够好。
对于这样的事情,我认为最简单的方法是在收集键时断言键确实是对象的键:
const keys = Object.keys(obj) as (keyof T)[];
对于您的getKeysGen
函数,一个问题是Object
您想要的是 Object 构造函数object
- 但即使那样,您也无法获得在没有泛型的情况下每次调用函数时传递的对象的类型。否则,你只有keyof typeof o
whereo
是一个普通的对象。
推荐阅读
- flutter - Flutter 网页上的 Index.html
- r - 有了这些等式,如果我们知道一年内每个部门工作的初始人数,我们就可以估计下一年的人数
- sql-server - 为什么我的应用程序 docker 没有连接到我的数据库 docker?
- python - 使用 .fillna 将一列中的 NA 值替换为另一列中的值
- rabbitmq - 磁盘满后的 RabbitMQ 恢复队列
- java - 如何从android studio中的recycler视图将数据添加到SQLite数据库中
- java - 生成像素样式真实类型字体的位图(Java.awt)
- angular - 为什么选项/标志在我的角度 CLI 上不起作用?
- react-native - React Native - 如果数组中的所有内容都包含
- python - django和django rest框架的区别