使用字符串类型参数访问枚举时出现 TypeScript TS7015 错误

Posted

技术标签:

【中文标题】使用字符串类型参数访问枚举时出现 TypeScript TS7015 错误【英文标题】:TypeScript TS7015 error when accessing an enum using a string type parameter 【发布时间】:2016-07-18 21:34:30 【问题描述】:

我是 TypeScript 的新手,我不明白我需要做什么来修复生成 TS7015 错误的行(使用字符串变量引用枚举成员),因为紧随其后的行没有错误(引用使用字符串文字的枚举成员):

enum State 
    Happy = 0,
    Sad = 1,
    Drunk = 2


function Emote(enumKey:string) 
    console.log(State[enumKey]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
    console.log(State["Happy"]); // no error

"noImplicitAny": true设置在项目的tsconfig.json中检测到错误

在项目的tsconfig.json中设置"noImplictAny": false未检测到错误

我正在编译 "ntypescript": "^1.201603060104.1"

我现在正在使用"tsc": "1.8.10"进行编译

C:>npm install -g typescript

`-- typescript@1.8.10

验证安装:

C:\>tsc --version

Version 1.8.10

这是我的tsconfig.json 文件:


  "compileOnSave": true,
  "compilerOptions": 
    "target": "ES5",
    "module": "System",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": true,
    "noImplicitAny": true,
    "sourceMap": true,
    "mapRoot": "map/",
    "diagnostics": true
  ,
  "exclude": [
    "node_modules",
    "typings"
  ]

这是编译器的输出:

C:\>tsc

test.ts(8,17): error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.

【问题讨论】:

您在寻找什么样的答案?您已经注意到将noImplicitAny 设置为false 会使错误消失... 我不想关闭 noImplicitAny 检查,而是想修复代码以使其通过 noImplicitAny 检查。但更重要的是,我不明白为什么第一个引用错误,第二个引用通过(从类型上讲,两个枚举引用的类型是相同的......或者他们真的不是,我只是错过了一些东西(可能很明显) ) 您使用的是什么版本的打字稿?我没有得到该代码的隐式任何类型错误。 "noImplicitAny": true,版本 1.8.2,没有错误,State[enumKey] ntypescript 看起来主要是为那些想直接使用 TypeScript 编译器 API 的人准备的。我想你想要typescript... 【参考方案1】:

我怀疑这与 TS 1.8.x 在这些情况下对字符串文字的新支持有关。 TS 碰巧知道“Happy”是一个有效的字符串索引,但它不知道enumKey 是否会是。您可以通过将其转换为 <any> 来修复它,如下所示:

function Emote(enumKey:string) 
    console.log(State[enumKey]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
    console.log(State["Melancholy"]); // error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
    console.log(State["Happy"]); // no error
    console.log(State[<any>enumKey]); // no error
    console.log(State[<any>"Melancholy"]); // no error

(顺便说一句,我认为这是新的:我无法在 1.8.9 中重现此错误,但一旦升级到 1.8.10,我就可以了。)

另外有趣的是,我本来希望这可以在没有错误的情况下工作,但事实并非如此:

function TypedEmote(enumKey:'Happy'|'Sad'|'Drunk')
    console.log(State[enumKey]);

一定是关于我不理解的 TS 规范的某些内容,或者他们可能还没有解决这个问题。

【讨论】:

有趣的是,“Melancholy”也出现了错误——让我怀疑编译器推断出有一个(未命名的)派生类型的字符串,并且仅限于“Happy”、“Sad”和“醉” --- 也许我可以明确定义这样的类型并使用它...... @Neoheurist - 这或多或少是我在上面的 TypedEmote() 方法中尝试使用 'Happy'|'Sad'|'Drunk' 类型所做的。就像我说的,是的,我认为它应该有效,但似乎没有。很想知道你是否能找到办法。 state: State = State[&lt;any&gt;"Happy"] 也不起作用 - “类型 'string' 不可分配给类型 'State'” @AlexOkrushko 不幸的是,在这种情况下,它似乎需要两边都有一个any 类型,就像我在这里所做的if(&lt;any&gt;this.gravity === GravityType[&lt;any&gt;dir]) 或者,看看Sharpiro's answer,它是一个bit 更优雅。【参考方案2】:
var stateName = "Happy"
var state = <State>parseInt(State[<any>stateName]);

为了让编译器满意,我必须这样做

【讨论】:

它有效,但它很丑......史蒂文的解决方案要好得多。 (但请注意,它只是 TS 2.1+,所以 YMMV)【参考方案3】:

您可以使用编译器选项来防止此错误,而不会丢失整个严格的空检查

"suppressImplicitAnyIndexErrors": true

https://www.typescriptlang.org/tsconfig#suppressImplicitAnyIndexErrors

【讨论】:

【参考方案4】:

如果您使用的是 TypeScript 2.1+,您可以将 enumKey 的类型更改为 keyof typeof State,如下所示:

function Emote(enumKey: keyof typeof State) ...

或者,如果函数的输入需要是string,则:

var state : State = State[enumKey as keyof typeof State];

解释:

因为enumKey 是任意的string,TypeScript 不知道enumKey 是否是State 的成员的名称,所以会产生错误。 TypeScript 2.1 引入了 keyof 运算符,它返回一个类型的已知公共属性名称的联合。使用keyof 可以让我们断言该属性确实在目标对象中。

然而,当你创建一个枚举时,TypeScript 实际上会生成一个 type(通常是 number 的子类型)和一个 value(枚举对象)您可以在表达式中引用)。当您编写keyof State 时,您实际上将获得number 的文字属性名称的联合。要获取枚举对象的属性名称,您可以使用keyof typeof State

来源:

https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/enums.html#enums-at-compile-time

【讨论】:

我更喜欢这个,而不是我们必须提供 TS 好处的其他解决方案。使用这个public rateType: keyof typeof RegularTypeEnum | BlockedTypeEnum;,任何人都可以理解该属性的可能值。谢谢。 你的回答太好了,应该在官方文档里。 我很欣赏这个答案,但令人恼火的是,类型安全总是想办法将非常简单明了的代码变成类型声明的混淆。 哇,这个答案对我有用,但看着这个让我头疼:State[enumKey as keyof typeof State]

以上是关于使用字符串类型参数访问枚举时出现 TypeScript TS7015 错误的主要内容,如果未能解决你的问题,请参考以下文章

将字符串的 2darray 作为参数传递时出现“错误:类型的数组值”

尝试在DynamoDb中保存枚举时出现“类型不受支持”错误

使用 JDBC 写入编写 AWS Glue DynamicFrame 时出现 PostreSQL 枚举问题

PLS-00306:调用 'GET_LINE' 时参数的数量或类型错误。在 PL/SQL 中的函数中传递字符串参数时出现此错误

typescri枚举enum

C语言数组或者枚举类型初始化时出现宏定义和包含头文件的奇怪语法