This is the archived version of Roland Weigelt's weblog that ran from 2003 to 2023 at weblogs.asp.net

A Stupid Little TypeScript Mistake (Part 2)

After my blog post in June, here is another tale from a C# developer getting his feet wet with TypeScript.

TypeScript’s type checking makes my life so much easier, but it does not catch everything. Recently I forgot an important part of a for-loop. Here is a stripped-down example:

var items=["item0", "item1", "item2"];
for (var n=0;items.length;n++)
{
    // ...
}

The code compiles, but runs into an endless loop – the “n<” is missing in the condition.

If I write similar code in C#…

var items=new[] {"item0", "item1", "item2"};
for (var n=0;items.Length;n++)
{
    // ...
}

… the compiler tells me what I did wrong:

Cannot implicitly convert type 'int' to 'bool'

Ok, another (TypeScript) lesson learned.

5 Comments

  • Thanks for this tip!

  • Hi! The comments did not work for a while. I received notification mails (including the comment text), but comments did not appear in the blog dashboard for approval. The issue has been fixed (thank you, Terri!) and I'll post the comments now manually in the order they came in.

  • Another of many reasons to avoid traditional three expression for loops for things that support iteration protocols. In C# the first instinct should be to use `foreach (var item in items) { }` instead, and JS/TS the equivalent of that these days is `for (const item of items) { }`. for/of is supported in most every browser today, but Typescript can also downlevel it to support older browsers if you really must. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of A trick to watch out for coming to JS/TS from C# is that for/in is a very old (JS 1.0) construct that mostly does the wrong thing but can't be removed because of backwards compatibility and given foreach/in it's easy to accidentally write for/in when you mean for/of when you are jumping back and forth between the two languages. The odd type signature of for/in in TS these days should catch you if you accidentally use the the wrong one, in many cases at least, and especially in cases involving arrays. Another JS/TS trick to watch out for when coming from C# is `var`: in JS var has "strange" scoping rules. var is another Old JS thing left in the language for backwards compatibility that given a language rewrite probably wouldn't still exist today. It "hoists" to the top of scopes, meaning that anything declared with var is accessible before the declaration and also accessible in higher scopes than you usually intend. If you are using modules (especially ES2015) the "blast radius" of an accidentally hoisted var always stops at the module but in the bad old days there were a lot of "safe" vars that accidentally became global variables. Best practice these days in JS/TS is to always use `let` and `const` for your variable declarations. Those follow "lexical scoping" rules that fit a lot more what you are used to expecting in a language like C#, no surprise hoisting and no use before declaration. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

  • You may want to look into eslint for typescript - it has e.g. a rule for strict boolean expressions which you can activate. Also, these days you could use „for (let item of items) { … }“

  • To be fair to TypeScript, this is a JavaScript issue. The `for` statement's test parameter requires a truthy expression and not a bool. Hence any expression that can be either 'truthy' or 'falsy' can be used, even for(var n =0; "hello"; n++) is valid!