Typescript-使用Enums作为索引签名类型时没有索引签名

时间:2019-04-12 20:53:12

标签: node.js typescript

我具有以下类型结构:

export type Method1 = (id: string, param: string) => Promise<any>

export enum ValuesList {
  VALUE1 = 'VALUE1',
  VALUE2 = 'VALUE2'
}

export type ValuesMap = {
  [key in ValuesList]: {
    callMethod: Method1
  }
}

export const methodsMap: ValuesMap = {
  [ValuesList.VALUE1]: {
    callMethod: lib.method
  },
  [ValuesList.VALUE2]: {
    callMethod: lib2.method
  }
}

在应用程序的某些部分,我想映射一些列表以动态调用此方法:

methodsMap[target].callMethod(data.id, data.param)

通过打字稿返回以下问题:

Element implicitly has an 'any' type because type 'ValuesMap' has no index signature.ts(7017)

打字稿无法将ValuesMap识别为带有索引的元素。如果我将ValuesMap改为使用[key: string]而不是[key in ValuesList],则可以使用,但是我想保留[key in ValuesList]

2 个答案:

答案 0 :(得分:1)

首先,让我们回顾一些术语。在TypeScript中,索引签名可以是字符串或数字,但不能更窄。如果您不只是使用string类型,而是通过文字(即属性,而不是索引签名)显式指定类型。这就是为什么枚举从不具有类型签名,而是具有属性的原因。

type A = {
   [key: string]: number // this is index signature
};

type B = {
   [key in 'foo' | 'bar']: number // this is a property 
}

现在是实际代码。您发布的代码片段似乎运行良好。当您将鼠标悬停在名称ValuesMap上时,工具提示会显示为:

type ValuesMap = { VALUE1: { callMethod: Method1; }; VALUE2: { callMethod: Method1; }; }

因此,实际上,它包含枚举中的两个值。因此,问题必须是您用作索引的target。因为TypeScript抱怨没有索引签名,所以我最好的猜测是您使用的target的类型为string,因此可能不是该枚举的值。 (您可以将鼠标悬停在其上方以查看其类型。)由于TypeScript希望防止您在未定义的情况下调用callMethod,因此它开始对您大吼大叫,直到将target限制为正确的值为止。 / p>

答案 1 :(得分:1)

如果您想使用 enum 作为变量来检查值:

如果你有

export enum ValuesList {
  VALUE1 = 'VALUE1',
  VALUE2 = 'VALUE2'
}

然后使用:

someVariable: { [key: string]: ValuesList } = ValuesList

代替:

someVariable: ValuesList = ValuesList