Why combine operators
Real rules rarely fit a single comparison. "Let a person in if they are a special student, or if their age is between 18 and 30" has three conditions and two different connectors. TypeScript lets you build such rules by mixing &&, || and ! in one expression, but the meaning depends on how the parts are grouped.
Grouping with parentheses
Consider this expression:
7 >= 10 && (5 == 7 || 9 < 12) // false
The parentheses group 5 == 7 and 9 < 12 into one condition. The expression then reads as condition1 && condition2:
condition1is7 >= 10, which isfalse.condition2is(5 == 7 || 9 < 12), which istrue, since9 < 12holds.
An and needs both sides to be true, and one is false, so the whole thing is false.
Move the parentheses and the meaning changes:
(7 >= 10 && 5 == 7) || 9 < 12 // true
Now it reads as condition1 || condition2. Here condition1 is (7 >= 10 && 5 == 7), which is false, and condition2 is 9 < 12, which is true. An or needs only one true side, so the whole thing is true. The same four pieces and the same operators give opposite answers, just because of where the parentheses sit.
Precedence: what happens without parentheses
When parentheses are missing, TypeScript follows a fixed order of precedence. From strongest to weakest, the logical operators go: ! first, then &&, then ||. Comparisons like < and == bind tighter than all three, so they are evaluated first. That means a || b && c is read as a || (b && c):
console.log(true || false && false);
console.log((true || false) && false);
true
false
The first line groups the and first: false && false is false, and true || false is true. The second forces the or first: true || false is true, and true && false is false.
You do not need to memorise the table. Add parentheses whenever you mix && and ||: they cost nothing, and the next reader does not have to remember the order.
TypeScript details
- Short-circuiting still applies. In
a || (b && c), ifais true, nothing else is evaluated. Ina && (b || c), ifais false, nothing else is. - Mixing with
??needs parentheses. The nullish operator??cannot be placed next to||or&&without them. Without parentheses, TypeScript reports an error and the JavaScript is a syntax error. - No chained comparisons.
18 <= age <= 30does not mean what it means in mathematics. Write two comparisons joined with&&:age >= 18 && age <= 30.
The exercise
The code gives you specialStudent, a boolean, and age, a number. Someone is let in when they are a special student or their age is between 18 and 30, both limits included. Otherwise, the program prints that they are not allowed.
- Write the age check as one unit:
age >= 18 && age <= 30. Both comparisons are inclusive, so 18 and 30 are accepted. - Put it in parentheses and join it with
specialStudentusing||. The parentheses are not required, because&&already binds tighter than||, but they show the grouping. - Log
"Let him in!"inside theif. - Add an
elseblock that logs"Not allowed", for anyone who fails both checks.
let specialStudent: boolean = false;
let age: number = 23;
if (specialStudent || (age >= 18 && age <= 30)) {
console.log("Let him in!");
} else {
console.log("Not allowed");
}
With the starting values, specialStudent is false, but the age check is true because 23 lies between 18 and 30. An or needs one true side, so the program prints:
Let him in!
Change age to 31 and both sides are false, so the output becomes Not allowed. Change specialStudent to true and every age is let in, because the left side of the or is true and the right side is never evaluated.
Common mistakes
- Using
||inside the age range.age >= 18 || age <= 30is true for every number, since any number is at least 18 or at most 30. - Using
&&between the two main conditions.specialStudent && (...)would let in only special students whose age is in the range. - Using
>or<for the age limits. The limits are inclusive, so 18 and 30 must be let in. - Misplaced parentheses.
(specialStudent || age >= 18) && age <= 30rejects special students older than 30.
Key takeaways
- Parentheses decide how conditions are grouped, and different grouping can give opposite results.
- Without them,
!binds first, then&&, then||. - Write parentheses whenever you mix
&&and||, even where the precedence would give the right answer. - Range checks need two comparisons joined with
&&.