I am 99% certain that this is indeed the case. Non-nullable types are one of my favorite new additions to TypeScript.
But it goes further than that. TypeScript 2 adds control flow analysis, so adding to the top of a function that accepts a string or an array:
if (typeof someVarThatCanBeStringOrArrayOfStrings === "string") {
// turn string into array
}
any code below it can safely assume that the variable is string[], as well as the rest of the code that calls this function if this variable is returned.
You are almost correct -- it's just that it's not a "safe" assumption.
In your example, the JS interpreter will not throw an error when one provides a number (for example). Your code could break things. But why would this happen?
It's completely unrelated to TypeScript.
A number could be provided by the data, which in all likelihood is JSON from the network (eg: HTTP request or message queue body). Strongly typed languages will give you strongly typed data to protect you from this, but a dynamic language like JS doesn't afford you the same protection.
TypeScript doesn't mitigate this issue -- nor could it. TypeScript ensures your plumbing fits together, not that the sludge flowing through it won't cause a mess.
A strongly typed language will throw an exception before unexpected behavior can occur, JS on the other-hand will attempt to continue. It rarely happens, but since it does you can't say it safely works properly.
That's a good point, but I don't quite see how a strongly typed language fixes this issue. Could you elaborate on that?
If a strongly typed language receives data that is malformed, wouldn't the same problem arise? Isn't it always the case that you only have control over your own plumbing, and put up defenses to deal with external input?
(I have little experience with strongly typed languages, so I'm really interested to understand this a bit better)