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.
| Operator | Name | Example | Result |
|---|---|---|---|
+ | Addition | 5 + 3 | 8 |
- | Subtraction | 5 - 3 | 2 |
* | Multiplication | 5 * 3 | 15 |
/ | Division | 15 / 3 | 5 |
% | Modulus (remainder) | 5 % 3 | 2 |
** | Exponentiation | 2 ** 3 | 8 |
++ | Increment | x++ | x + 1 |
-- | Decrement | x-- | 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).
| Operator | Name | Example | Description |
|---|---|---|---|
== | Equality | 5 == "5" | Loose equality (type coercion) |
=== | Strict Equality | 5 === 5 | Checks value AND type |
!= | Inequality | 5 != "6" | Loose inequality |
!== | Strict Inequality | 5 !== "5" | Different value OR type |
> | Greater than | 7 > 5 | Returns true |
< | Less than | 3 < 5 | Returns true |
>= | Greater or equal | 5 >= 5 | Returns true |
<= | Less or equal | 3 <= 5 | Returns 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.
| Operator | Name | Description | Example |
|---|---|---|---|
&& | AND | True if both operands are true | true && false โ false |
|| | OR | True if at least one operand is true | true || false โ true |
! | NOT | Inverts 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.
| Operator | Name | Example | Equivalent To |
|---|---|---|---|
= | Assignment | x = 5 | Assigns 5 to x |
+= | Add and assign | x += 3 | x = x + 3 |
-= | Subtract and assign | x -= 3 | x = x - 3 |
*= | Multiply and assign | x *= 3 | x = x * 3 |
/= | Divide and assign | x /= 3 | x = x / 3 |
%= | Modulus and assign | x %= 3 | x = x % 3 |
**= | Exponent and assign | x **= 2 | x = 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 like0,"", andfalse - 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 | undefinedafter 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):
| Level | Operators | Description |
|---|---|---|
| 1 | ++ -- | Increment/Decrement |
| 2 | ! typeof | Unary 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/undefinedtypeof: check value type (limited for objects)instanceof: check class membership
Best Practices:
- โ
Use
===instead of== - โ
Use
??instead of||for defaults - โ
Use
?.to avoid null reference errors - โ Use parentheses for complex expressions
- โ Keep increment/decrement on separate lines
- โ 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
- TypeScript Official Documentation - Operators: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions
- MDN Web Docs - Expressions and Operators: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
- 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! ๐ช