[英]How to determine the type of object with possible and string and numeric indices in typescript?
My function can work with array and objects. 我的函数可以使用数组和对象。 Objects have keys with string-type and array have keys with numeric-type.
对象的键类型为字符串型,数组的键类型为数字型。 Also there can be object without keys.
也可以有没有钥匙的物体。
I determine two interfaces and one type: 我确定两个接口和一种类型:
interface IObjectStringKey {
[key: string]: any
}
interface IObjectNumberKey {
[key: number]: any
}
// object with key-string, key-number or without key
type IObjectAnyKey = IObjectNumberKey | IObjectStringKey | {};
My function get argument - array of this type and I want to iterate through every key of every object. 我的函数获取参数-这种类型的数组,我想遍历每个对象的每个键。
function myFunction( ...sources: IObjectAnyKey[]) {
const values = [];
for (let i = 0; i < sources.length; i++) {
const source: IObjectAnyKey = sources[i];
for (let key in source) {
const val = source[key];
}
}
}
You can see error in playground: typescript.org/myTask (you need to enable 'noImplicitAny' in Options) 您可以在操场上看到错误: typescript.org/myTask (您需要启用“noImplicitAny”的选项)
Error is "Element implicitly has an 'any' type because type 'IObjectAnyKey' has no index signature". 错误是“元素隐式具有'any'类型,因为类型'IObjectAnyKey'没有索引签名”。 How can I solve this problem?
我怎么解决这个问题? I need to know how to define type with different index type.
我需要知道如何用不同的索引类型定义类型。 Or, maybe, there is some other solve.
或者,也许还有其他解决方法。
IObjectAnyKey
is essentially equivalent to the empty type {}
. IObjectAnyKey
本质上等效于空类型{}
。 The type {}
matches pretty much every value (except for null
and undefined
), so the union of {}
with anything else (except a possibly null
or undefined
type) is also {}
. 类型
{}
几乎匹配每个值( null
和undefined
除外),因此{}
与其他任何值(可能为null
或undefined
类型除外)的联合也是{}
。 TypeScript therefore doesn't know what keys are in source
( keyof IObjectAnyKey
is equivalent to never
, the empty set) so it balks at indexing into it. 因此,TypeScript不知道
source
有哪些键( keyof IObjectAnyKey
等效于never
,空集),因此它不愿为其建立索引。
Your IObjectStringKey
is only slightly narrower than {}
. 您的
IObjectStringKey
仅比{}
窄。 Since TypeScript introduced implicit index signatures , any type with known literal keys can be widened to a type with an index signature whose value type is the union of all value types. 由于TypeScript引入了隐式索引签名 ,因此任何具有已知文字键的类型都可以扩展为带有索引签名的类型,该索引签名的值类型为所有值类型的并集。 For example:
例如:
const literalKeys = {a: 'hey', b: 2, c: true};
const indexSignature: {[k: string]: string | number | boolean} = literalKeys;
The above assignment works because literalKeys
is compatible with the index signature. 上面的分配之所以
literalKeys
是因为literalKeys
与索引签名兼容。 Therefore, if you make myFunction()
accept an array of IObjectStringKey
, it shouldn't prevent you from calling it: 因此,如果使
myFunction()
接受IObjectStringKey
的数组 ,则不应阻止您调用它:
function myFunction(...sources: IObjectStringKey[]) {
const values = [];
for (let i = 0; i < sources.length; i++) {
const source = sources[i];
for (let key in source) {
const val = source[key]; // no error
}
}
}
myFunction({},{a: 'hey'},{b: 2}); // still works
If you insist on using (the relatively useless) IObjectAnyKey
, you can always just do a type assertion to make the error go away: 如果您坚持使用(相对没用的)
IObjectAnyKey
,则始终可以执行类型声明来使错误消失:
function myFunction(...sources: IObjectAnyKey[]) {
const values = [];
for (let i = 0; i < sources.length; i++) {
const source = sources[i];
for (let key in source) {
const val = (source as any)[key]; // explicitly "any"
}
}
}
Hope that helps. 希望能有所帮助。 Good luck.
祝好运。
in javascript the property key of an object is always converted to a string, so obj[1]
is equivalent to obj['1']
and you can only implement the first interface IObjectStringKey
. 在javascript中,对象的属性键始终会转换为字符串,因此
obj[1]
等效于obj['1']
并且您只能实现第一个接口IObjectStringKey
。 in general, you should avoid using pseudo arrays and use real arrays if all your data is contiguous. 通常,如果所有数据都是连续的,则应避免使用伪数组,而应使用实数数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.