This feature is also there in C and C++ and probably other languages. The catch is that js seems to have inherited the syntax but not the scoping rules.
const a = 5;
console.log(a)
{
const a = 10;
console.log(a)
}
console.log(a)
5
10
5
What we are missing from say Rust in js is the blocks being expressions, though there is a proposal ("do expressions") to allow this: const a = do {
if (b) { 5 } else { 10 }
};
https://github.com/tc39/proposal-do-expressionsI personally dislike JavaScript. Even modern JavaScript. But this is a bullshit reason to hate on JavaScript.
Similarly, if I have a discriminant union `type FooBar = "foo" | "bar";`, TypeScript seems to know that `if (["foo", "bar"].includes(x)) {...}` exhaustively handles all permutations of `FooBar` (no need for a `switch` statement with explicit arms).
The static typing really helps me avoid a bunch of "undefined is not a function" stuff that I would waste time with in JavaScript.
Pretty cool stuff!
The catch with JS is that variable scoping rules are different when you use 'var', if you use 'let' and 'const' the scoping rules work like most programmers would expect for block statements.