TypeScript TS7015 error when accessing an enum using a string type parameter

别来无恙 提交于 2019-12-17 17:56:17

问题


I am new to TypeScript and I don't understand the what I need to do to fix the line that generates the TS7015 error (referencing an enum member using a string variable) because the line immediately following that does not error (referencing an enum member using a string literal):

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 is set in the project's tsconfig.json the error is detected

"noImplictAny": false is set in the project's tsconfig.json no error is detected

I'm compiling with "ntypescript": "^1.201603060104.1"

I'm now compiling with "tsc": "1.8.10"

C:>npm install -g typescript

`-- typescript@1.8.10

Verifying installation:

C:\>tsc --version

Version 1.8.10

Here's my tsconfig.json file:

{
  "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"
  ]
}

Here's the compiler output:

C:\>tsc

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

回答1:


If you're using TypeScript 2.1+, you can change enumKey's type to keyof typeof State, like this:

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

or, if the function's input is required to be a string, this:

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

Explanation:

The error is generated because TypeScript, being an arbitrary string, doesn't know whether enumKey is the name of a member of State. TypeScript 2.1+ introduced the keyof operator which returns a union of the known, public property names of a type. Using keyof allows us to assert that the property is indeed in the target object.

However, when you create an enum, TypeScript actually produces both a type (which is always a subtype of number) and a value (the enum object that you can reference in expressions). When you write keyof State, you're actually going to get a union of the literal property names of number. To instead get the property names of the enum object, you can use keyof typeof State.

Sources:

https://github.com/Microsoft/TypeScript/issues/13775#issuecomment-276381229 https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types




回答2:


I suspect it has to do with TS 1.8.x's new support for string literals in these situations. TS happens to know that "Happy" is a valid string index, but it doesn't know whether enumKey will be or not. You can fix it by casting it to an <any>, like so:

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
}

(BTW, I think this is new: I couldn't reproduce this error with 1.8.9, but as soon as I upgraded to 1.8.10, I could.)

Also interestingly, I would have expected this to work without the error, but it doesn't:

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

Must be something about the TS spec I don't understand, or perhaps they just haven't gotten around to fixing that bit yet.




回答3:


You can prevent this error with the compiler option without loosing the whole strict null checks

"suppressImplicitAnyIndexErrors": true



回答4:


var stateName = "Happy"
var state = <State>parseInt(State[<any>stateName]);

This is what I had to do to make the compiler happy



来源:https://stackoverflow.com/questions/36316326/typescript-ts7015-error-when-accessing-an-enum-using-a-string-type-parameter

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!