I was thinking about how TypeScript removed the need to think about "JavaScript gotchas" from years gone by.
Adding numbers instead of combining text
Adding text "5" to number 100 makes "1005".
// ❌ (No warning, charges $1005)
const price = 100;
const tax = "5";
const total = price + tax; // "1005"
// ✅ Catches it
const price: number = 100;
const tax: string = "5";
const total = price + tax;
// 🔴 Error: Cannot apply '+' to 'number' and 'string'.
Calling something that doesn't exist
Running a function that wasn't passed crashes the page.
// ❌ Crashes
function sendNotification(config) {
config.onSuccess(); // Uncaught TypeError: config.onSuccess is not a function
}
sendNotification({});
// ✅ Forces safe checking
type Config = { onSuccess?: () => void };
function sendNotification(config: Config) {
config.onSuccess();
// 🔴 Error: 'onSuccess' is possibly 'undefined'.
config.onSuccess?.(); // Safe!
}
Spelling mistakes in property names
A single wrong letter gives undefined instead of a crash, hiding the bug.
// ❌ Quietly fails
const user = { firstName: "Sam" };
console.log(user.firstname); // Output: undefined
// ✅ Spots the typo
const user = { firstName: "Sam" };
console.log(user.firstname);
// 🔴 Error: Property 'firstname' does not exist on user. Did you mean 'firstName'?
Forgetting required information
Skipping an argument turns math into NaN (Not a Number).
function multiply(a, b) {
return a * b;
}
multiply(5); // Output: NaN
// ✅ Enforces all parameters
function multiply(a: number, b: number) {
return a * b;
}
multiply(5);
// 🔴 Error: Expected 2 arguments, but got 1.
Accidentally changing important data
Any piece of code can accidentally overwrite critical settings.
// ❌ Allows accidental changes
const config = { adminUrl: "https://wordpress.com/admin" };
config.adminUrl = "https://danger.com"; // Changed!
// ✅ Locks data down
type Config = { readonly adminUrl: string };
const config: Config = { adminUrl: "https://site.com/admin" };
config.adminUrl = "https://hacked.com";
// 🔴 Error: Cannot assign to 'adminUrl' because it is read-only.
6. Forgetting a scenario in a list
Adding a new state gets ignored if you forget to handle it.
// ❌ Returns nothing for new states
function getStatus(status) {
if (status === "PAID") return "Green";
if (status === "PENDING") return "Yellow";
// Forgot "REFUNDED"! Returns undefined.
}
// ✅ Demands every case is handled
type Status = "PAID" | "PENDING" | "REFUNDED";
function getStatus(status: Status): string {
if (status === "PAID") return "Green";
if (status === "PENDING") return "Yellow";
// 🔴 Error: Function lacks ending return statement. You forgot 'REFUNDED'!
}
The 0 treated as "false" trap
The Problem: JS treats 0 as "empty", so 0 items defaults to 10.
// ❌ 0 triggers the fallback
function setQuantity(quantity) {
return quantity || 10;
}
setQuantity(0); // Output: 10 (Wrong!)
// ✅ Pairs with ?? to handle 0 correctly
function setQuantity(quantity?: number) {
return quantity ?? 10; // Only defaults if null or undefined
}
setQuantity(0); // Output: 0 (Correct!)
Comparing completely unrelated things
JS equality rules lead to absurd true results.
// ❌ Nonsensical comparison passes
if ([] == false) {
// Runs! An empty array equals false in JS...
}
// ✅ Blocks bad comparisons
if ([] == false) {}
// 🔴 Error: This comparison is unintentional. Array and boolean have no overlap.
Accidentally ruining original lists
.sort() alters the original array instead of making a new one.
// ❌ Mutates original array silently
function getSorted(items) {
return items.sort();
}
const names = ["Bob", "Alice"];
getSorted(names); // 'names' is now changed to ["Alice", "Bob"]
// ✅ Protects original arrays
function getSorted(items: readonly string[]) {
return items.sort();
// 🔴 Error: 'sort' does not exist on 'readonly string[]'. Make a copy first!
}
Trusting random data from the internet
Reading missing fields from API data crashes the app.
// ❌ Crashes if structure changes
const data = JSON.parse(apiResponse);
console.log(data.user.name); // Uncaught TypeError: Cannot read property 'name' of undefined
// ✅ Forces you to verify before accessing
const data: unknown = JSON.parse(apiResponse);
// console.log(data.user.name); 🔴 Error: 'data' is of type 'unknown'.
// Must check shape first:
if (data && typeof data === "object" && "user" in data) {
// Now it's safe to use!
}
Top comments (0)