1 < x < 3 actually is doing this:
(1 < x) < 3
Or even more long form:
const tempVarA = 1 < x
const tempVarB = tempVarA < 3
So 1 < x is either true or false. Then the next step is true < 3 or false < 3. Those don't make much sense as comparisons, but let's see what javascript does with that:
console.log(true < 3) // true
console.log(false < 3) // true
Weird, but let's dig deeper:
console.log(true >= 0) // true
console.log(true >= 1) // true
console.log(true >= 2) // false
console.log(false >= 0) // true
console.log(false >= 1) // false
console.log(false >= 2) // false
It seems that true is being treated as 1 and false is being treated as 0. To verify that let's compare with == (instead of ===) so that it coerces the type of the data for us.
console.log(true == 1) // true
console.log(true == 0) // false
console.log(false == 1) // false
console.log(false == 0) // true
So 1 < x < 3 is always true because false becomes 0 or true becomes 1, and both 0 and 1 always less than 3.
Explanation:
in javascript, comparison operators <, <=, >, >=, ==, and != coerce their operands to make them comparable when they are different types. So when comparing a boolean to a number it coverts the boolean to a number, 0 or 1.
This is why you should almost always use === instead of ==, and why this is a type error in typescript:
const a = true < 3
// Operator '<' cannot be applied to types 'boolean' and 'number'.(2365)
Short version
Javascript and typescript lack a chainable comparison operator.
Did you mean to do this?
1 < x && x < 3