The Operator Survival Guide for TypeScript Devs
Vladyusha
Posted on November 26, 2024
Picture this: You're debugging your TypeScript code at 2 a.m.
Sipping on your nth cup of coffee(I don't drink coffee), and staring at line like this:
if (a == b) { /* mysterious bug */ }
“What's the problem? They look equal enough!” you think. But then you remember your strict buddy ===
, who clearly needs to step in here.
TypeScript, like any good mentor, loves precision and order. Operators are its way of making sure your code knows exactly what you want from it.
In this article, we'll dive into the world of TypeScript operators, discover who they are, how they differ, and when to befriend them (or avoid them entirely).
Content:
- Logical operators
- Relational operators
- Bitwise operators
- Ternary Operator
- Type Operators
Logical operators
Logical AND (&&
)
Explanation
The &&
operator checks if both conditions are true. If one fails, it's game over.
Example:
Imagine you're trying to buy snacks from vending machine. You need money and the machine needs to works.
const hasMoney = true
const machineWorks = false
if (hasMoney && machineWorks) {
console.log("Yay! Got my snack!")
} else {
console.log("No snack for you.")
}
“I had the money, but the machine didn't cooperate. Guess I'm snackless today.”
Logical OR (||
)
Explanation:
The ||
operator checks if at least one condition is true. It's all about backup plans!
Example:
You're craving pizza, but the local pizza is closed. Luckily, you've got leftovers in the fridge.
const pizzaPlaceOpen = false
const haveLeftovers = true
if (pizzaPlaceOpen || haveLeftovers) {
console.log("Dinner is saved!")
} else {
console.log("Time to go hungry.")
}
“Pizza place closed? No problem. Cold pizza it is!”
Logical NOT (!
)
Explanation:
The !
operator flips a condition. True becomes false, and false becomes true.
Example:
Your friends says they're not coming to the party. But you know them: if they says no, it usually means yes.
const friendSaidNo = true
if (!friendSaidNo) {
console.log("Surprise! They’re at the party!")
} else {
console.log("Guess they’re serious this time.")
}
“Told you, they always show up last minute!”
Relational Operators in Action (==
, ===
, !=
, !==
)
Equality (==
)
Explanation:
The ==
operator checks if two values are loosely equal. It doesn’t care about their type, as long as they look the same.
Example:
Imagine your friend asks for “5 apples,” but you only have “5” written on a sticky note. They shrug and say, “Close enough!”
const applesOnNote = "5"
const applesNeeded = 5
if (applesOnNote == applesNeeded) {
console.log("Friend: Good enough, I’ll take it.")
} else {
console.log("Friend: Nope, I need *real* apples.")
}
“Turns out, a number written on paper isn’t quite the same as an actual apple.”
Strict Equality (===
)
Explanation:
The ===
operator is more picky. It checks both value and type. No shortcuts here!
Example:
This time, your friend insists: “I need 5 actual apples, not just a sticky note with the number!”
if (applesOnNote === applesNeeded) {
console.log("Friend: Perfect, these are actual apples.")
} else {
console.log("Friend: Hey, this is just a note! Not what I asked for!")
}
“Lesson learned: Strict friends need strict checks.”
Inequality (!=
)
Explanation:
The !=
operator checks if two values are not loosely equal. It doesn’t mind small mismatches, like different types.
Example:
You promise your friend you’ll bring “not oranges.” You show up with a basket of bananas.
const fruitBrought = "bananas"
if (fruitBrought != "oranges") {
console.log("Friend: Thanks! At least it’s not oranges.")
} else {
console.log("Friend: Seriously? I said no oranges!")
}
“Bananas passed the test, but only because the bar was so low.”
Strict Inequality (!==
)
Explanation:
The !==
operator makes sure values are not equal in value or type. It’s the strict version of !=
.
Example:
Your friend clarifies: “I don’t just want ‘not oranges,’ I want something completely different, like actual fruit!”
const gift = "orange"
if (gift !== "oranges") {
console.log("Friend: Thanks, this is acceptable.")
} else {
console.log("Friend: Come on, I said no oranges, and this is one.")
}
“When your friend’s picky, even being close isn’t good enough.”
Let's get some rest
Here you can go with a cup of tea or coffee
Bitwise Operators in Action
"When your computer starts playing with bits like building blocks."
Bitwise AND (&
)
Explanation:
The &
operator compares two numbers bit by bit and keeps a 1
only where both bits are 1
.
Example:
Imagine two friends trying to agree on a movie night. They’ll only go if both want to see the same movie.
const myPreference = 0b1010 // Movies A and C
const friendPreference = 0b1100 // Movies B and C
const mutualChoice = myPreference & friendPreference // Only C (0b1000)
console.log(mutualChoice ? "Movie night is on!" : "No agreement, no movie.")
"Friendship survives, but only if we both agree!"
Bitwise OR (|
)
Explanation:
The |
operator compares two numbers bit by bit and keeps a 1
if either bit is 1
.
Example:
This time, you and your friend decide to list all the movies you’d consider watching — even if only one of you likes them.
const combinedChoices = myPreference | friendPreference // A, B, C (0b1110)
console.log("Here’s our list of possible movies:", combinedChoices)
"Compromise: we’ll pick from everyone’s favorites!"
Bitwise XOR (^
)
Explanation:
The ^
operator compares two numbers bit by bit and keeps a 1
only where the bits are different.
Example:
You and your friend each make a unique suggestion for dinner. XOR helps filter out any overlap.
const uniqueChoices = myPreference ^ friendPreference // A and B (0b0110)
console.log("These are unique picks:", uniqueChoices)
"Let’s focus on what makes us different — in a good way!"
Bitwise NOT (~
)
Explanation:
The ~
operator flips all the bits of a number. A 1
becomes 0
, and vice versa.
Example:
Your pessimistic friend looks at your list and says, “Here’s what’s NOT on the table.”
const allOptions = 0b1111 // All movies
const notMyPreference = ~myPreference & allOptions // Movies B and D
console.log("Movies I don’t want:", notMyPreference)
"Fine, let’s skip my least favorites..."
Left Shift (<<
)
Explanation:
The <<
operator moves the bits of a number to the left, filling in with zeroes on the right. It’s like multiplying by 2 for every shift.
Example:
Imagine packing for a trip. Each bag can hold double the amount if you rent a bigger car.
const bags = 0b0010 // 2 bags
const biggerCar = bags << 2 // 8 bags
console.log("We can pack this many bags now:", biggerCar)
"Time to bring more snacks!"
Sign-propagating Right Shift (>>
)
Explanation:
The >>
operator shifts bits to the right, keeping the sign (positive or negative). It’s like dividing by 2 for every shift.
Example:
You’re splitting up leftovers. Start with a big portion and share until it’s all gone.
let leftovers = 0b1000 // 8 portions
const nextPortion = leftovers >> 1 // 4 portions
console.log("Leftovers after sharing:", nextPortion)
"Sharing is caring, but don’t leave me hungry!"
Zero-fill Right Shift (>>>
)
Explanation:
The >>>
operator shifts bits to the right, filling with zeroes. It works the same for positive numbers but ignores signs for negatives.
Example:
Imagine clearing out space in your garage by throwing out junk. New space is always clean (zeros).
const junk = -8 // Negative binary
const clearedSpace = junk >>> 1
console.log("Cleaned-up garage space:", clearedSpace)
"Who cares if it’s negative? Clean slate it is!"
Ternary Operator
Explanation:
The ternary operator (condition ? expressionIfTrue : expressionIfFalse
) is a shorthand for making quick decisions. Think of it as flipping a coin when you need to make a choice, but smarter — it looks at the condition and picks the right answer for you.
Example:
Imagine you’re deciding whether to take an umbrella before heading out. If it’s raining, you take one; otherwise, you don’t bother.
const isRaining = true
const umbrella = isRaining ? "Take the umbrella!" : "No umbrella needed."
console.log(umbrella)
"The sky decides for me: rain or shine, I’m ready!"
When NOT to use it:
The ternary operator is great for short and simple choices, but if you’re stacking a dozen conditions, you’ll end up with something that looks like a spaghetti monster:
// Don’t do this!
const mood = isRaining ? "sad" : isSunny ? "happy" : isCloudy ? "meh" : "confused";
"Readable code is happy code. Don’t overdo it!"
Type Operators
typeof
Explanation:
The typeof
operator is like a detective — it checks the type of a value at runtime or extracts the type of a variable for use in your TypeScript code.
Example:
Imagine someone hands you a mystery box. You use a label scanner (typeof
) to figure out if it’s a fruit or a gadget.
const mysteryBox = "apple"
const boxType = typeof mysteryBox
console.log(boxType === "string" ? "It’s a fruit!" : "Unknown gadget.")
"When in doubt, always check the label."
keyof
Explanation:
The keyof
operator creates a type that includes all the keys of an object. Think of it as flipping through a dictionary to see all the available words.
Example:
Your friend hands you a shopping list, and you check what categories (keys) they’ve written down:
type ShoppingList = {
fruits: string[]
veggies: string[]
snacks: string[]
}
type ListCategories = keyof ShoppingList // 'fruits' | 'veggies' | 'snacks'
const chosenCategory: ListCategories = "fruits" // valid!
"When you know all the categories, choosing one is easy!"
Mapped Types
Explanation:
Mapped types let you apply the same transformation to all properties of a type. Think of it as photocopying a document but adding a filter to every page.
Example:
Suppose you have a task list, and you need to mark every task as optional.
type TaskList = {
homework: string
chores: string
shopping: string
};
type OptionalTaskList = {
[Key in keyof TaskList]?: TaskList[Key]
};
// Result: All tasks become optional
const myTasks: OptionalTaskList = { homework: "Math" } // Valid!
"It’s like giving yourself an excuse to skip a task — because now it’s optional!"
Conditional Types
Explanation:
Conditional types let you write logic to decide between types based on conditions. It’s like asking, “If this happens, what should I do?”
Example:
Imagine deciding the size of a meal based on hunger.
type MealSize<HungerLevel> = HungerLevel extends "starving"
? "large"
: "small"
type MyMeal = MealSize<"starving"> // 'large'
type FriendMeal = MealSize<"full"> // 'small'
"If you’re starving, go big. If you’re full, maybe just dessert!"
Practical Use:
Conditional types are powerful for creating reusable, dynamic types in your code. For example:
type Response<T> = T extends "success" ? { data: string } : { error: string };
"Adapt your type to the situation!"
A Quick Note from Your Friendly Guide
Before we wrap up, I have to confess: I didn’t include every single operator here. Why? Well, some operators are so simple they don’t need much explaining (like the classic =
— we’ve all seen that one in action). Others just didn’t make the cut because I wanted to keep things snappy and focus on the fun and fascinating ones.
But hey, don’t just take my word for it! TypeScript has a treasure trove of operators waiting for you to explore. Head over to the official TypeScript documentation and give them a look. Trust me, your future self (and your code) will thank you.
"Because even the small and simple operators deserve some love, right?"
End
Thx for reading)
Subscribe to my telegram
Posted on November 26, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.