Reputation: 1133
I have this really easy problem, where I want to loop through an Object in TypeScript.
const an_object = {
one: 1,
two: 2,
three: 3
};
for (let key in an_object) {
let value = an_object[key];
// Do something with value
}
This row let value = an_object[key];
is causing a TypeScript error:
[react-scripts] Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ one: number; two: number; three: number; }'.
I'm new to TypeScript and don't really understand the problem.
This works fine on JavaScript but not on TypeScript.
Any suggestions on how to loop through an object in TypeScript correctly, without getting errors?
Upvotes: 8
Views: 7447
Reputation: 148
As @OuuGiii puts it, it's TYPEscript. So just define the key for the loop variable. However, if you are lazy like me and don't wanna define an entire interface notice that you can do something like this:
{ // To make "key" a local variable it must be in a "block" (braces).
// If a block is not used, you cannot use another loop with this iteration
// variable This is especially important if, much like me, you have a bad habit
// of defining "i"s for all the loops.
let key: keyof typeof an_object;
for (key in an_object) {
let value /*: typeof an_object[typeof key] */ = an_object[key];
// Do something with value
}
}
Upvotes: 4
Reputation: 1133
TypeScript is named TYPEScript for a reason.
The problem is that it's not specified what will be inside the object.
Any suggestions on how to loop through an object in TypeScript correctly, without getting errors?
To do this correctly you should specify what is inside the object. This can be done by:
interface MyObjectsInterface {
[key: string]: number;
}
const an_object: MyObjectsInterface = {
one: 1,
two: 2,
three: 3
};
for (let key in an_object) {
let value: number = an_object[key];
// Do something with value
}
In this way, you will always know what will be inside an object.
Upvotes: 5
Reputation: 51037
For this purpose, I usually write a helper function, so that my "for each object property" loops can be written like follows:
objForEach(an_object, (k, v) => {
console.log('key', k, 'value', v);
});
The implementation is below. Helpfully, by making it generic, the parameters k
and v
can have their types inferred correctly depending on an_object
:
function objForEach<T>(obj: T, f: (k: keyof T, v: T[keyof T]) => void): void {
for (let k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
f(k, obj[k]);
}
}
}
Note that I've used hasOwnProperty
to check that the property belongs to the object itself rather than another object in its prototype chain (see e.g. this question).
Upvotes: 4