I'm trying to use Enum values as the keys for an object, expecting this to preserve the type when I get the value, but I'm getting Element implicitly has an 'any' type because expression of type 'string' can't be used to index type
.
export enum TaskType {
Classification = 'classification',
Extraction = 'extraction'
}
const comparisons: { [name in TaskType]: Function } = {
'classification': () => false,
'extraction': () => false
}
for (const taskType in comparisons) {
// I expect func to be of type Function, but I get a TypeScript error:
// Element implicitly has an 'any' type because expression of type 'string' can't be used to index type
const func = comparisons[taskType]
}
I've tried using const func = comparisons[taskType as keyof TaskType]
but this doesn't work either.
CodePudding user response:
taskType
in for-in
is a string type, you cannot map it with an enum type under comparisons
.
You can cast it to TaskType
enum by as
like the below code snippet instead.
Side note, instead of using a static string key for comparisons
, you can use enum keys directly on it.
export enum TaskType {
Classification = 'classification',
Extraction = 'extraction'
}
const comparisons: { [name in TaskType]: Function } = {
[TaskType.Classification]: () => false,
[TaskType.Extraction]: () => false
}
for (const taskType in comparisons) {
const func = comparisons[taskType as TaskType] //cast it to an enum type
}
CodePudding user response:
As mentioned in the another answer, you can use to cast the key which is fine.
However I've got an alternative in your case by switching using Object.keys(comparisons)
, but unfortunately with the current definition of ObjectConstructor
, it doesn't support to infer the correct type as well.
interface ObjectConstructor {
//...
keys(o: object): string[]
keys(o: {}): string[]
}
But there's a solution to override it. Let's do following steps:
- Create your
typings/override.d.ts
with following data and put it as part ofinclude
in your configuration:
// typings/override.d.ts
type ObjectKeys<T> = T extends object
? (keyof T)[]
: T extends number
? []
: T extends Array<any> | string
? string[]
: never;
interface ObjectConstructor {
keys<T>(o: T): ObjectKeys<T>;
}
// tsconfig.json
{
// ...
include: [..., 'typings']
}
Now, you can re-write your code with Object.keys
way:
Object.keys(comparisons).forEach((k) => {
// `k` is now `TaskType` type
});