A Practical Guide to TypeScript Logical Operators

In programming, we constantly need to make decisions. Should this code run? Is this user allowed to see that page? To make these decisions, we evaluate conditions, and the fundamental tools for this are logical operators. They are the building blocks of control flow in any language, including TypeScript.

Logical operators work with boolean values (true and false) to produce a single boolean result. Let’s dive into the three core logical operators you’ll use every day: Logical AND (&&), Logical OR (||), and Logical NOT (!).


1. Logical AND (&&)

The Logical AND operator, represented by &&, returns true only if both of its operands are true. If either operand is false, the result will be false.

Think of it like this: “I will go to the park if it is sunny and I have finished my work.” Both conditions must be met.

Truth Table for AND (&&)

Operand AOperand BA && B
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

Example in Code

Let’s see how we can use this to check if a user is eligible for admin access.

let isLoggedIn = true;
let hasAdminRole = false;

let canAccessAdminPanel = isLoggedIn && hasAdminRole;

console.log(Can access admin panel? ${canAccessAdminPanel}); // Output: Can access admin panel? false

// Let's change the role
hasAdminRole = true;
canAccessAdminPanel = isLoggedIn && hasAdminRole;

console.log(Can access admin panel now? ${canAccessAdminPanel}); // Output: Can access admin panel now? true

In the first check, because hasAdminRole is false, the entire expression evaluates to false. In the second, both conditions are true, so the result is true.


2. Logical OR (||)

The Logical OR operator, written as ||, returns true if at least one of its operands is true. It only returns false if both operands are false.

An analogy: “You can have a discount if you are a new customer or you have a coupon code.” Only one of these needs to be true to get the discount.

Truth Table for OR (||)

Operand AOperand BA || B
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

Example in Code

Imagine we want to send a notification if an order is either “shipped” or “delivered”.

let orderStatus = "processing";
let isShipped = orderStatus === "shipped"; // false
let isDelivered = orderStatus === "delivered"; // false

let shouldSendNotification = isShipped || isDelivered;

console.log(Send notification? ${shouldSendNotification}); // Output: Send notification? false

// Now, let's update the status
orderStatus = "shipped";
isShipped = orderStatus === "shipped"; // true
isDelivered = orderStatus === "delivered"; // false

shouldSendNotification = isShipped || isDelivered;

console.log(Send notification now? ${shouldSendNotification}); // Output: Send notification now? true

As soon as one of the conditions (isShipped) becomes true, the whole expression becomes true.


3. Logical NOT (!)

The Logical NOT operator (!) is a bit different. It’s a unary operator, meaning it works on only one operand. Its job is simple: it inverts the boolean value. If the operand is true, it returns false, and if the operand is false, it returns true.

Think of it as simply “not”. “Run this code if the user is not an admin.”

Truth Table for NOT (!)

Operand A!A
truefalse
falsetrue

Example in Code

We can use this to check if a window is closed before trying to open it.

let isWindowOpen = false;

if (!isWindowOpen) {
    console.log("The window is closed. Opening it now.");
    // code to open the window...
    isWindowOpen = true;
}

console.log(Is the window open? ${isWindowOpen}); // Output: Is the window open? true


An Important Concept: Short-Circuiting

Both && and || operators exhibit a behavior called “short-circuiting,” which is an important optimization. The interpreter evaluates the expression from left to right and stops as soon as it can determine the final outcome.

  • For Logical AND (&&): If the first operand is false, the overall result must be false. Therefore, TypeScript doesn’t even bother to evaluate the second operand.
  • For Logical OR (||): If the first operand is true, the overall result must be true. Therefore, the second operand is never evaluated.

Short-Circuiting Example

function isExpensiveCheck() {
    console.log("Checking if the operation is expensive...");
    return true; // Simulating a costly function
}

console.log("--- Testing AND (&&) short-circuit ---");
let result1 = false && isExpensiveCheck(); // isExpensiveCheck() is NOT called
console.log(result1); // false

console.log("--- Testing OR (||) short-circuit ---");
let result2 = true || isExpensiveCheck(); // isExpensiveCheck() is NOT called
console.log(result2); // true

In the output, you would not see the “Checking if the operation is expensive…” message printed for either test. This is short-circuiting in action! This is extremely useful for preventing unnecessary, computationally expensive function calls or avoiding errors, like trying to access a property on a null object.


Combining Logical Operators

The real power comes from combining these operators to create complex decision-making logic. When you combine them, it’s a best practice to use parentheses () to control the order of evaluation and make your code easier to read.

Let’s check if a user can post a comment. They must be logged in, and they must either be a subscriber or not be banned.

let isLoggedIn = true;
let isSubscriber = false;
let isBanned = false;

// Good: Using parentheses for clarity
let canPostComment = isLoggedIn && (isSubscriber || !isBanned);

// Let's trace it:
// 1. !isBanned -> !false -> true
// 2. isSubscriber || true -> false || true -> true
// 3. isLoggedIn && true -> true && true -> true

console.log(Can user post a comment? ${canPostComment}); // Output: Can user post a comment? true

// What if the user is a subscriber but is banned?
isSubscriber = true;
isBanned = true;

canPostComment = isLoggedIn && (isSubscriber || !isBanned);

// Let's trace it now:
// 1. !isBanned -> !true -> false
// 2. isSubscriber || false -> true || false -> true
// 3. isLoggedIn && true -> true && true -> true

console.log(Can a banned subscriber post? ${canPostComment}); // Output: Can a banned subscriber post? true

Parentheses ensure that the || and ! operations are evaluated first, and their result is then used in the && operation, just as we intended.


Conclusion

Logical operators are the bedrock of conditional logic in TypeScript. By mastering how &&||, and ! work, along with the performance benefit of short-circuiting, you can write cleaner, more efficient, and more expressive code. They empower you to control your application’s flow with precision, making your programs smarter and more responsive to different conditions.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.