You are viewing a preview of this lesson. Sign in to start learning
Back to TypeScript

Core Operators

Explore TypeScript operators including nullish coalescing, non-null assertion, spread, and instanceof operators.

Core Operators in TypeScript

Master TypeScript's core operators with free flashcards and spaced repetition practice. This lesson covers arithmetic, logical, comparison, and assignment operatorsโ€”essential building blocks for writing effective TypeScript code. Understanding these operators will enable you to perform calculations, make decisions, and manipulate data with confidence.

Welcome to TypeScript Operators! ๐Ÿ’ป

Operators are the fundamental symbols and keywords that allow you to perform operations on values and variables in TypeScript. Just as mathematical operators like + and - work with numbers, TypeScript operators work with various data types to create expressions and logic in your programs.

In this comprehensive lesson, you'll learn:

  • Arithmetic operators for mathematical calculations
  • Comparison operators for evaluating conditions
  • Logical operators for combining boolean expressions
  • Assignment operators for updating variables
  • Type-specific operators unique to TypeScript

Let's dive into the world of TypeScript operators! ๐Ÿš€

Core Concepts: Understanding TypeScript Operators

Arithmetic Operators ๐Ÿงฎ

Arithmetic operators perform mathematical calculations on numeric values. TypeScript inherits these from JavaScript and adds type safety.

OperatorNameExampleResult
+Addition5 + 38
-Subtraction5 - 32
*Multiplication5 * 315
/Division15 / 35
%Modulus (remainder)5 % 32
**Exponentiation2 ** 38
++Incrementx++x + 1
--Decrementx--x - 1

๐Ÿ’ก Key Insight: The + operator also concatenates strings! When used with strings, it joins them together:

let greeting: string = "Hello" + " " + "World"; // "Hello World"
let mixed = "Score: " + 42; // "Score: 42" (number converts to string)

Increment and Decrement Nuances:

let x = 5;
let y = x++; // Post-increment: y = 5, then x becomes 6
let z = ++x; // Pre-increment: x becomes 7, then z = 7

Comparison Operators โš–๏ธ

Comparison operators evaluate relationships between values and return boolean results (true or false).

OperatorNameExampleDescription
==Equality5 == "5"Loose equality (type coercion)
===Strict Equality5 === 5Checks value AND type
!=Inequality5 != "6"Loose inequality
!==Strict Inequality5 !== "5"Different value OR type
>Greater than7 > 5Returns true
<Less than3 < 5Returns true
>=Greater or equal5 >= 5Returns true
<=Less or equal3 <= 5Returns true

โš ๏ธ Critical Distinction: Always prefer === and !== in TypeScript!

// Loose equality (avoid this!)
5 == "5"    // true (type coercion happens)
0 == false  // true (unexpected behavior)

// Strict equality (use this!)
5 === "5"   // false (different types)
0 === false // false (number vs boolean)

Logical Operators ๐Ÿ”€

Logical operators combine or invert boolean expressions, crucial for control flow and conditional logic.

OperatorNameDescriptionExample
&&ANDTrue if both operands are truetrue && false โ†’ false
||ORTrue if at least one operand is truetrue || false โ†’ true
!NOTInverts boolean value!true โ†’ false

Truth Table Reference:

AND (&&) Operator:
  A     B   |  A && B
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 true  true |  true
 true  false|  false
 false true |  false
 false false|  false

OR (||) Operator:
  A     B   |  A || B
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 true  true |  true
 true  false|  true
 false true |  true
 false false|  false

Short-Circuit Evaluation: Logical operators use short-circuit behavior:

// AND: stops at first false
false && expensiveFunction() // expensiveFunction never runs

// OR: stops at first true
true || expensiveFunction()  // expensiveFunction never runs

Assignment Operators ๐Ÿ“

Assignment operators store values in variables, with compound versions that combine operations.

OperatorNameExampleEquivalent To
=Assignmentx = 5Assigns 5 to x
+=Add and assignx += 3x = x + 3
-=Subtract and assignx -= 3x = x - 3
*=Multiply and assignx *= 3x = x * 3
/=Divide and assignx /= 3x = x / 3
%=Modulus and assignx %= 3x = x % 3
**=Exponent and assignx **= 2x = x ** 2

Type-Specific Operators in TypeScript ๐ŸŽฏ

TypeScript adds several operators specifically for working with types:

The typeof Operator:

Returns the type of a value as a string:

typeof 42           // "number"
typeof "hello"      // "string"
typeof true         // "boolean"
typeof undefined    // "undefined"
typeof null         // "object" (JavaScript quirk!)
typeof {}           // "object"
typeof []           // "object" (arrays are objects)
typeof function(){} // "function"

The instanceof Operator:

Checks if an object is an instance of a specific class:

class Dog {
  bark() { console.log("Woof!"); }
}

class Cat {
  meow() { console.log("Meow!"); }
}

let pet = new Dog();
pet instanceof Dog  // true
pet instanceof Cat  // false

The Nullish Coalescing Operator (??):

Returns the right operand when the left is null or undefined, otherwise returns the left:

let userInput: string | null = null;
let displayName = userInput ?? "Guest"; // "Guest"

let value = 0;
let result = value ?? 42; // 0 (because 0 is NOT null/undefined)

๐Ÿ’ก Difference from OR (||):

let value = 0;
value || 42  // 42 (because 0 is falsy)
value ?? 42  // 0 (because 0 is not null/undefined)

// Use ?? when you want to keep falsy values like 0, "", false

The Optional Chaining Operator (?.):

Safely accesses nested properties without errors if intermediate values are null or undefined:

interface User {
  name: string;
  address?: {
    street: string;
    city: string;
  };
}

let user: User = { name: "Alice" };

// Without optional chaining (unsafe!):
let city = user.address && user.address.city; // undefined

// With optional chaining (safe!):
let safeCity = user.address?.city; // undefined (no error)

// Chain multiple levels:
let zipCode = user.address?.details?.zipCode; // undefined

Ternary (Conditional) Operator โ“

The ternary operator is a compact way to write simple if-else conditions:

Syntax: condition ? valueIfTrue : valueIfFalse

let age: number = 18;
let canVote: string = age >= 18 ? "Yes" : "No"; // "Yes"

let score: number = 85;
let grade: string = score >= 90 ? "A" : score >= 80 ? "B" : "C"; // "B"

๐Ÿง  Memory Device: Think of ? as asking a question, : as providing alternatives.

Ternary Structure:

   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚ CONDITION   โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ”‚
          โ–ผ
      condition?
       โ•ฑ      โ•ฒ
      โ•ฑ        โ•ฒ
   TRUE      FALSE
     โ”‚          โ”‚
     โ–ผ          โ–ผ
  value1    value2

Detailed Examples with Explanations ๐Ÿ“š

Example 1: Building a Shopping Cart Calculator ๐Ÿ›’

Let's create a practical example combining arithmetic and comparison operators:

interface CartItem {
  name: string;
  price: number;
  quantity: number;
}

function calculateCart(items: CartItem[], taxRate: number = 0.08): void {
  let subtotal: number = 0;
  
  // Use compound assignment to accumulate total
  for (let item of items) {
    subtotal += item.price * item.quantity; // Arithmetic operators
  }
  
  let tax: number = subtotal * taxRate;
  let total: number = subtotal + tax;
  
  // Use comparison and ternary operators for discount
  let discount: number = subtotal >= 100 ? subtotal * 0.1 : 0;
  let finalTotal: number = total - discount;
  
  console.log(`Subtotal: $${subtotal.toFixed(2)}`);
  console.log(`Tax: $${tax.toFixed(2)}`);
  console.log(`Discount: $${discount.toFixed(2)}`);
  console.log(`Total: $${finalTotal.toFixed(2)}`);
}

let cart: CartItem[] = [
  { name: "Laptop", price: 899.99, quantity: 1 },
  { name: "Mouse", price: 29.99, quantity: 2 }
];

calculateCart(cart);
// Output:
// Subtotal: $959.97
// Tax: $76.80
// Discount: $95.997
// Total: $940.77

Key Takeaways:

  • The += operator efficiently accumulates values in loops
  • Arithmetic operators chain naturally: item.price * item.quantity
  • Ternary operator provides clean conditional logic for discounts
  • Comparison operators (>=) control business logic flow

Example 2: User Authentication Validator ๐Ÿ”

Combining logical operators for complex validation:

interface LoginCredentials {
  username: string;
  password: string;
  rememberMe?: boolean;
}

function validateLogin(creds: LoginCredentials): boolean {
  // Validation rules using logical operators
  let isUsernameValid: boolean = 
    creds.username.length >= 3 && creds.username.length <= 20;
  
  let hasUpperCase: boolean = /[A-Z]/.test(creds.password);
  let hasNumber: boolean = /[0-9]/.test(creds.password);
  let isLengthValid: boolean = creds.password.length >= 8;
  
  // Combine conditions with AND operator
  let isPasswordValid: boolean = 
    hasUpperCase && hasNumber && isLengthValid;
  
  // Use NOT operator to invert checks
  let noSpaces: boolean = !creds.username.includes(" ");
  
  // Final validation: all conditions must be true
  return isUsernameValid && isPasswordValid && noSpaces;
}

let user1: LoginCredentials = {
  username: "john_doe",
  password: "SecurePass123"
};

console.log(validateLogin(user1)); // true

let user2: LoginCredentials = {
  username: "ab",  // Too short!
  password: "weak"
};

console.log(validateLogin(user2)); // false

Key Takeaways:

  • The && operator chains multiple validation requirements
  • The ! operator inverts conditions for negative checks
  • Logical operators enable complex business rules in readable code
  • Each validation step stores in a descriptive variable for clarity

Example 3: Smart Default Values with Nullish Coalescing ๐ŸŽฏ

Using TypeScript-specific operators for safer code:

interface UserPreferences {
  theme?: string;
  fontSize?: number;
  notifications?: boolean;
  volume?: number;
}

function applyUserSettings(prefs: UserPreferences): void {
  // Use ?? to provide defaults only for null/undefined
  let theme: string = prefs.theme ?? "light";
  let fontSize: number = prefs.fontSize ?? 16;
  let notifications: boolean = prefs.notifications ?? true;
  
  // Important: ?? keeps falsy values like 0
  let volume: number = prefs.volume ?? 50;
  
  console.log(`Theme: ${theme}`);
  console.log(`Font Size: ${fontSize}px`);
  console.log(`Notifications: ${notifications}`);
  console.log(`Volume: ${volume}%`);
}

// Test with explicit 0 value (should NOT use default!)
applyUserSettings({ volume: 0 });
// Output:
// Theme: light
// Font Size: 16px
// Notifications: true
// Volume: 0%  โ† Correctly keeps 0!

// Compare with || operator (wrong behavior):
function buggySettings(prefs: UserPreferences): void {
  let volume: number = prefs.volume || 50; // Bug: treats 0 as missing!
  console.log(`Volume: ${volume}%`);
}

buggySettings({ volume: 0 });
// Output: Volume: 50%  โ† Wrong! Lost the user's 0 setting

Key Takeaways:

  • The ?? operator is perfect for default values in TypeScript
  • Unlike ||, it preserves falsy values like 0, "", and false
  • Use ?? when distinguishing between "not provided" and "explicitly false"
  • Optional properties (?) pair naturally with nullish coalescing

Example 4: Safe Property Access Chain ๐Ÿ”—

Optional chaining prevents runtime errors:

interface Company {
  name: string;
  address?: {
    street?: string;
    city?: string;
    country?: string;
    coordinates?: {
      latitude: number;
      longitude: number;
    };
  };
}

function getCompanyLocation(company: Company): string {
  // Optional chaining safely navigates nested properties
  let city: string | undefined = company.address?.city;
  let country: string | undefined = company.address?.country;
  
  // Combine with ?? for complete safety
  let location: string = `${city ?? "Unknown"}, ${country ?? "Unknown"}`;
  
  // Chain even deeper
  let lat: number | undefined = company.address?.coordinates?.latitude;
  let lon: number | undefined = company.address?.coordinates?.longitude;
  
  if (lat !== undefined && lon !== undefined) {
    location += ` (${lat}, ${lon})`;
  }
  
  return location;
}

let company1: Company = {
  name: "TechCorp",
  address: {
    city: "San Francisco",
    country: "USA",
    coordinates: { latitude: 37.7749, longitude: -122.4194 }
  }
};

console.log(getCompanyLocation(company1));
// Output: San Francisco, USA (37.7749, -122.4194)

let company2: Company = {
  name: "StartupXYZ"
  // No address provided
};

console.log(getCompanyLocation(company2));
// Output: Unknown, Unknown
// No errors thrown!

Key Takeaways:

  • The ?. operator prevents "Cannot read property of undefined" errors
  • Chain multiple ?. operators for deeply nested structures
  • Combine ?. and ?? for robust null-safe code
  • Return type becomes Type | undefined after optional chaining

Common Mistakes to Avoid โš ๏ธ

Mistake 1: Confusing == with ===

// โŒ WRONG: Loose equality causes unexpected behavior
if (userInput == null) { // Matches BOTH null AND undefined!
  console.log("No input");
}

// โœ… CORRECT: Use strict equality
if (userInput === null) { // Only matches null
  console.log("Explicitly null");
}

// โœ… BETTER: Check for both null and undefined explicitly
if (userInput === null || userInput === undefined) {
  console.log("Missing value");
}

// โœ… BEST: Use nullish coalescing
let value = userInput ?? "default";

Why it matters: Type coercion with == can create subtle bugs that only appear in production.

Mistake 2: Forgetting Operator Precedence

// โŒ WRONG: Unexpected order of operations
let result = 10 + 5 * 2; // 20, not 30! (* has higher precedence)

// โœ… CORRECT: Use parentheses for clarity
let result = (10 + 5) * 2; // 30

// โŒ WRONG: Logical operators confused
if (age > 18 && age < 65 || isEmployee) { // Which grouping?
  // Unclear logic!
}

// โœ… CORRECT: Explicit grouping
if ((age > 18 && age < 65) || isEmployee) {
  // Clear: (adult AND not senior) OR employee
}

Operator Precedence Quick Reference (high to low):

LevelOperatorsDescription
1++ --Increment/Decrement
2! typeofUnary operators
3**Exponentiation
4* / %Multiplication, Division, Modulus
5+ -Addition, Subtraction
6< > <= >=Comparison
7=== !==Equality
8&&Logical AND
9||Logical OR
10??Nullish coalescing
11? :Ternary
12= += etc.Assignment

Mistake 3: Misusing || Instead of ??

// โŒ WRONG: Using || loses falsy values
function setVolume(level?: number): number {
  return level || 50; // Bug: level=0 returns 50!
}

setVolume(0);   // Returns 50 (wrong!)
setVolume(100); // Returns 100 (correct)

// โœ… CORRECT: Use ?? for nullish values only
function setVolume(level?: number): number {
  return level ?? 50; // Only uses 50 if null/undefined
}

setVolume(0);   // Returns 0 (correct!)
setVolume(100); // Returns 100 (correct)

Mistake 4: Pre vs. Post Increment Confusion

// โŒ WRONG: Unexpected behavior
let count = 5;
let values = [count++, count++, count++];
console.log(values); // [5, 6, 7] (post-increment)
console.log(count);  // 8

// โŒ WRONG: Using increment in complex expressions
let x = 10;
let result = x++ + ++x; // Confusing! result = 10 + 12 = 22

// โœ… CORRECT: Use increment on separate lines
let x = 10;
x++; // 11
let result = x + 1; // Clear and predictable

Mistake 5: Not Using Optional Chaining

// โŒ WRONG: Manual null checking (verbose and error-prone)
function getCity(user: User): string {
  if (user && user.address && user.address.city) {
    return user.address.city;
  }
  return "Unknown";
}

// โœ… CORRECT: Optional chaining (clean and safe)
function getCity(user: User): string {
  return user?.address?.city ?? "Unknown";
}

Mistake 6: Incorrect Type Checking

// โŒ WRONG: typeof doesn't distinguish arrays from objects
let arr = [1, 2, 3];
if (typeof arr === "object") { // true (but also true for {}!)
  console.log("It's an object");
}

// โœ… CORRECT: Use Array.isArray() for arrays
if (Array.isArray(arr)) {
  console.log("It's an array");
}

// โŒ WRONG: typeof null returns "object" (JavaScript quirk)
let value = null;
if (typeof value === "object") { // true (surprising!)
  console.log("Unexpected");
}

// โœ… CORRECT: Check for null explicitly
if (value === null) {
  console.log("It's null");
}

Key Takeaways ๐ŸŽฏ

๐Ÿ“‹ Core Operators Quick Reference

Arithmetic Operators:

  • Basic: +, -, *, /, %, **
  • Shorthand: ++, --, +=, -=, *=, /=

Comparison Operators:

  • Always use strict: ===, !== (avoid ==, !=)
  • Relational: <, >, <=, >=

Logical Operators:

  • && (AND): both must be true
  • || (OR): at least one must be true
  • ! (NOT): inverts boolean
  • Short-circuit evaluation applies

TypeScript-Specific:

  • ?. Optional chaining: safe nested access
  • ?? Nullish coalescing: default only for null/undefined
  • typeof: check value type (limited for objects)
  • instanceof: check class membership

Best Practices:

  1. โœ… Use === instead of ==
  2. โœ… Use ?? instead of || for defaults
  3. โœ… Use ?. to avoid null reference errors
  4. โœ… Use parentheses for complex expressions
  5. โœ… Keep increment/decrement on separate lines
  6. โœ… Use ternary for simple conditions only

๐Ÿง  Memory Devices

"Triple Equals, Triple Safe" โ†’ Always use === for comparisons

"Question Mark Safety Chain" โ†’ ?. and ?? work together:

  • ?. asks "Does this exist?"
  • ?? says "If not, use this instead"

"AND needs ALL, OR needs ONE" โ†’ && requires all true, || needs just one

Precedence Mnemonic: "PEMDAS Plus Logic"

  • Parentheses first
  • Exponents (**)
  • Multiplication/Division/Modulus
  • Division (covered above)
  • Addition/Subtraction
  • Subtraction (covered above)
  • Then: comparison โ†’ equality โ†’ logical โ†’ ternary โ†’ assignment

๐Ÿค” Did You Know?

The ?? nullish coalescing operator was added to JavaScript in ES2020 specifically to solve the "falsy value" problem with ||. Before this, developers had to write verbose checks like value !== null && value !== undefined ? value : default.

The optional chaining operator ?. was introduced at the same time and has prevented countless "Cannot read property of undefined" runtime errors!

๐Ÿ“š Further Study

  1. TypeScript Official Documentation - Operators: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions
  2. MDN Web Docs - Expressions and Operators: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
  3. TypeScript Deep Dive - Operators: https://basarat.gitbook.io/typescript/future-javascript/null-propagation

๐Ÿ”ง Try This Mini-Exercise:

Create a function that calculates a discounted price with the following rules:

  • If quantity >= 10, apply 15% discount
  • If subtotal >= $100, apply additional 10% discount
  • Use optional chaining to safely access a customer loyalty discount
  • Use nullish coalescing for default tax rate of 8%

Combine all the operators you've learned in this lesson! ๐Ÿ’ช