简体   繁体   中英

Why does TypeScript complain about string index on an enum?

The TypeScript code below has errors about using a string index with an enum in some cases, but not in others. Also, in some environments, the code with "errors" runs anyway.

enum LMSRole {
  AccountAdmin = 'Account Admin',
  SupportConsultant = 'Support Consultant',
  StudentEnrollment = 'StudentEnrollment',
  TeacherEnrollment = 'TeacherEnrollment'
}

console.log(LMSRole.SupportConsultant) /* "Support Consultant" - OK */

const roles: String[] = ['AccountAdmin', 'SupportConsultant']
console.log(roles.map(r => LMSRole[r]))
/* Error given, yet runs on (http://typescriptlang.org/play)...
 * Type 'String' cannot be used as an index type. */

 console.log(LMSRole['SupportConsultant']) /* "Support Consultant" - OK */
/* In this example, a type of 'String' is used as an index,
 * but there's no error. Why? */

See this in action at typescriptlang.org's Playground .

What I don't understand is why in the map function, I get the error about using the string index. However, using a string directly to get a single value from the enum works without error.

I also don't understand why the Playground reports an error, but it runs anyway. On my own computer, if I try to run it, it will fail before anything is executed.

The type string may have more specific types. The type could be specific strings.

So when you do this:

const roles: string[] = ['AccountAdmin', 'SupportConsultant']
console.log(roles.map(r => LMSRole[r]))

roles is an array of string types. But the LMSRole only has very specific strings that you can use as an index, so you get the error.

Where here:

console.log(LMSRole['SupportConsultant'])

Typescript knows, because you directly used a string literal, what the specific type of that string is, and knows it's a good one.

If you changed that to:

LMSRole['SomethingElse']
//Element implicitly has an 'any' type because expression of type '"SomethingElse"' can't be used to index type 'typeof LMSRole'.
//  Property 'SomethingElse' does not exist on type 'typeof LMSRole'.(7053)

Then you get an error that makes sense.

You can force typescript to treat your array as constants, which lets it infer the specific strings types like so:

const roles = ['AccountAdmin', 'SupportConsultant'] as const
console.log(roles.map(r => LMSRole[r])) // no error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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