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

Posted

技术标签:

【中文标题】如何在打字稿中使用可能的字符串和数字索引确定对象的类型?【英文标题】:How to determine the type of object with possible and string and numeric indices in typescript? 【发布时间】:2018-09-16 07:58:08 【问题描述】:

我的函数可以处理数组和对象。对象具有字符串类型的键,数组具有数字类型的键。也可以有没有键的对象。

我确定了两个接口和一个类型:

interface IObjectStringKey 
  [key: string]: any

interface IObjectNumberKey 
  [key: number]: any

// object with key-string, key-number or without key
type IObjectAnyKey = IObjectNumberKey | IObjectStringKey | ;

我的函数获取参数 - 这种类型的数组,我想遍历每个对象的每个键。

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];
        
    

您可以在 Playground 中看到错误:typescript.org/myTask (您需要在 Options 中启用 'noImplicitAny')

错误是“元素隐式具有 'any' 类型,因为类型 'IObjectAnyKey' 没有索引签名”。我怎么解决这个问题?我需要知道如何定义具有不同索引类型的类型。或者,也许还有其他解决方案。

【问题讨论】:

嗯。我没有看到任何错误。 @TanDuong 您需要点击“选项”并选中“noImplicitAny” 【参考方案1】:

javascript中,对象的属性键总是转换为字符串,所以obj[1]等价于obj['1'],你只能实现第一个接口IObjectStringKey。一般来说,如果所有数据都是连续的,则应避免使用伪数组并使用真实数组。

【讨论】:

【参考方案2】:

IObjectAnyKey本质上等价于空类型 类型几乎匹配所有值(nullundefined 除外),因此 与其他任何值(可能是 nullundefined 类型除外)的联合也是 .因此,TypeScript 不知道 source 中的键是什么(keyof IObjectAnyKey 等同于 never,空集),因此它不愿对其进行索引。

您的IObjectStringKey 仅比 略窄。由于 TypeScript 引入了implicit index signatures,任何具有已知文字键的类型都可以扩展为具有索引签名的类型,其值类型是所有值类型的联合。例如:

const literalKeys = a: 'hey', b: 2, c: true;
const indexSignature: [k: string]: string | number | boolean = literalKeys;

上述分配有效,因为literalKeys 与索引签名兼容。因此,如果您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

如果你坚持使用(相对没用的)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"
    
  

希望对您有所帮助。祝你好运。

【讨论】:

以上是关于如何在打字稿中使用可能的字符串和数字索引确定对象的类型?的主要内容,如果未能解决你的问题,请参考以下文章

在打字稿中,如何检查字符串是不是为数字

在打字稿中,如何检查字符串是不是为数字

打字稿中的剂量[索引:字符串]是啥意思[重复]

如何将对象数组转换为在打字稿中具有动态键的单个对象

打字稿中迭代的索引签名

从打字稿中的索引文件导出JSON文件