113

TypeScript docs say nothing about loop like for or for-in. From playing with the language it seems that only any or string variables are supported in for loop.

Why has this decision been made?

Why not use the type information and have strongly-typed iteration variable?

5 Answers 5

162

In Typescript 1.5 and later, you can use for..of as opposed to for..in

var numbers = [1, 2, 3];

for (var number of numbers) {
    console.log(number);
}
Sign up to request clarification or add additional context in comments.

4 Comments

for...in iterates the keys of the objects in the collection, while for...of is the correct approach for iterating the objects themselves
for..of does not give you an iterator. So, if you're doing something like comparing consecutive values in an array, for..of is not the correct solution, for..in is. TypeScript is WRONG for artificially constraining how these constructs might be used.
just to add to this, if you need the index as well you can do for (var [i, number] of numbers.entries()) { }
how does this answer have that much likes? how does it even have 1 like? It misses the point, does not answer the question, and even misinforms people by suggesting that for..of is a replacement of for..in, while both are different and serve a different purpose.
78

TypeScript isn't giving you a gun to shoot yourself in the foot with.

The iterator variable is a string because it is a string, full stop. Observe:

var obj = {};
obj['0'] = 'quote zero quote';
obj[0.0] = 'zero point zero';
obj['[object Object]'] = 'literal string "[object Object]"';
obj[<any>obj] = 'this obj'
obj[<any>undefined] = 'undefined';
obj[<any>"undefined"] = 'the literal string "undefined"';

for(var key in obj) {
    console.log('Type: ' + typeof key);
    console.log(key + ' => ' + obj[key]);
}

How many key/value pairs are in obj now? 6, more or less? No, 3, and all of the keys are strings:

Type: string
0 => zero point zero
Type: string
[object Object] => this obj; 
Type: string
undefined => the literal string "undefined" 

5 Comments

OK... but a string is not as precise as "a key of this specific object". So how does one type keys of an object when iterating with a for in loop?
use for...of instead of for...in
That's for arrays not objects
True, I think what I meant was that for...in iterates over an object's property keys (ignoring those keyed with a symbol), so all the keys are strings by definition, as the answerer above points out. If you actually want to iterate over a collection, usually that collection won't be represented by keys in an object, but by an iterable of some king (e.g. an array), so you can use for...of. You get full type information this way.
Thanks for the clear explanation. It seems that Javascript only allows strings for object keys (they are cast when the values are stored if you console log the object you will see the previous entries are overwritten. The correct way to store a collection where you can use objects as the keys is with Set
36

The for-in statement is really there to enumerate over object properties, which is how it is implemented in TypeScript. There are some issues with using it on arrays.

I can't speak on behalf of the TypeScript team, but I believe this is the reason for the implementation in the language.

Comments

24

edit 2018: This is outdated, js and typescript now have for..of loops.
http://www.typescriptlang.org/docs/handbook/iterators-and-generators.html


The book "TypeScript Revealed" says

"You can iterate through the items in an array by using either for or for..in loops as demonstrated here:

// standard for loop
for (var i = 0; i < actors.length; i++)
{
  console.log(actors[i]);
}

// for..in loop
for (var actor in actors)
{
  console.log(actor);
}

"

Turns out, the second loop does not pass the actors in the loop. So would say this is plain wrong. Sadly it is as above, loops are untouched by typescript.

map and forEach often help me and are due to typescripts enhancements on function definitions more approachable, lke at the very moment:

this.notes = arr.map(state => new Note(state));

My wish list to TypeScript;

  1. Generic collections
  2. Iterators (IEnumerable, IEnumerator interfaces would be best)

Comments

1

For those who need a way to iterate through an object's properties while maintaining types in TS:


Method 1

You can use a helper function for type-safe keys

function typedKeys<T extends object>(obj: T): Array<keyof T> {
  return Object.keys(obj) as Array<keyof T>;
}

const obj: MyObject = { a: 1, b: 2 };

for (const key of typedKeys(obj)) {
  console.log(obj[key]);
}

Method 2

If you want to use the for..in loop

for (const key in obj) {
  if (Object.prototype.hasOwnProperty.call(obj, key)) {
    const typedKey = key as keyof MyObject;
    console.log(obj[typedKey]);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.