How do I prevent the error "Index signature of object type implicitly has an 'any' type" when compiling typescript with noImplicitAny flag enabled?

Asked 7 years ago
Viewed 239.59 k times

I always compile Typescript with the flag --noImplicitAny. This makes sense as I want my type checking to be as tight as possible.

My problem is that with the following code I get the error Index signature of object type implicitly has an 'any' type:

interface ISomeObject {
    firstKey:   string;
    secondKey:  string;
    thirdKey:   string;

let someObject: ISomeObject = {
    firstKey:   'firstValue',
    secondKey:  'secondValue',
    thirdKey:   'thirdValue'

let key: string = 'secondKey';

let secondValue: string = someObject[key];

Important to note is that the idea is that the key variable comes from somewhere else in the application and can be any of the keys in the object.

I've tried explicitly casting the type by:

let secondValue: string = <string>someObject[key];

Or is my scenario just not possible with --noImplicitAny?

asked 7 years ago

Correct Answer

Adding an index signature will let TypeScript know what the type should be.

In your case that would be [key: string]: string;

interface ISomeObject {
    firstKey:      string;
    secondKey:     string;
    thirdKey:      string;
    [key: string]: string;

However, this also enforces all of the property types to match the index signature. Since all of the properties are a string it works.

While index signatures are a powerful way to describe the array and 'dictionary' pattern, they also enforce that all properties match their return type.


If the types don't match, a union type can be used [key: string]: string|IOtherObject;

With union types, it's better if you let TypeScript infer the type instead of defining it.

// Type of `secondValue` is `string|IOtherObject`
let secondValue = someObject[key];
// Type of `foo` is `string`
let foo = secondValue + '';

Although that can get a little messy if you have a lot of different types in the index signatures. The alternative to that is to use any in the signature. [key: string]: any; Then you would need to cast the types like you did above.

answered 8 months ago

Other Answer

Another way to avoid the error is to use the cast like this:

let secondValue: string = (<any>someObject)[key]; (Note the parenthesis)

The only problem is that this isn't type-safe anymore, as you are casting to any. But you can always cast back to the correct type.

ps: I'm using typescript 1.7, not sure about previous versions.

answered 7 years ago