简体   繁体   English

如何在打字稿中使用可能的索引以及字符串和数字索引来确定对象的类型?

[英]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 {} . 类型{}几乎匹配每个值( nullundefined除外),因此{}与其他任何值(可能为nullundefined类型除外)的联合也是{} 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM