Why does this code work?
for (const i in undefined) {}
From for...in
- JavaScript | MDN:
The
for...in
statement iterates over all enumerable string properties of an object (ignoring properties keyed by symbols), including inherited enumerable properties.
But according to undefined
- JavaScript | MDN, undefined
has no enumerable property. So the for...in
loop shouldn't work on it.
The deno-ts linter says:
The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.
But according to
undefined
- JavaScript | MDN,undefined
has no enumerable property. So thefor...in
loop shouldn't work on it.
Looping over something that is "empty" means the loop is a no-op. Not that there would be an error. Consider this for..of
example:
const arr = [];
console.log("start loop");
for (const item of arr) {
console.log("item is", item);
}
console.log("end loop");
And with this consideration, let us look at for..in
where the behaviour is the same:
const object = {};
console.log("start loop");
for (const key in object) {
console.log("key is", key);
}
console.log("end loop");
Looping over an empty object with no enumerable properties using for..in
does not error.
The same applies to undefined
. It has no enumerable properties, so the loop is merely a no-op.
The deno-ts linter says:
The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'.
One of the things that linters do is detect potential problems. Writing a loop which is a guaranteed no-op does not seem like correct code. Same as if you had:
if (false)
doSomething();
or maybe a bit more complex (so it is not as easy to spot)
if (x === 1 && x === 2)
doSomething();
A linter should flag both of these for the same reason - the code is most likely a mistake because it is guaranteed to never execute.