TypeScript – Element implicitly has an 'any' type because expression of type 'string' can't be used to index type

Issue

Let’s say I have this:

const color = {
    red: null,
    green: null,
    blue: null
};

const newColor = ['red', 'green', 'blue'].filter(e => color[e]);

The error is in color[e] near the bottom with:

Element implicitly has an ‘any’ type because expression of type
‘string’ can’t be used to index type ‘{ red: null; green: null; blue:
null; }’. No index signature with a parameter of type ‘string’ was
found on type ‘{ red: null; green: null; blue: null; }’.

I tried looking everywhere on TypeScript docs, but how the heck am I suppose to interface this so it can accept color[e]?

Solution

The problem you’re having is not that color is the wrong type, but that TypeScript is inferring the type of ['red', 'green', 'blue'] to be string[]. Often that type of inference is desirable, since (for all the compiler knows) you might want to push 'purple' onto it. But in this case, you’d like the compiler to know that the only members are the three string literals 'red', 'green', and 'blue'. That is, you need a type at least as specific as Array<'red'|'green'|'blue'>.

Assuming you’re using TS3.4 or later, the easiest way to get this kind of type inference from the compiler is to use a const assertion:

const constAssertionTest = ["red", "green", "blue"] as const;
// const constAssertionTest: readonly ["red", "green", "blue"];

The as const causes the compiler to infer a tuple composed of exactly the three string literals in the array, in the exact order you’ve set. (It’s even a read-only tuple). That is good enough to fix your error:

const newColor = (['red', 'green', 'blue'] as const).filter(e => color[e]); // okay

All right, hope that helps. Good luck!

Link to code

Answered By – jcalz

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published