Skip to Content
Course content

16: Practice Exercise: Type Coercion Puzzles

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent more hours than I care to admit debugging a "ghost in the machine" that turned out to be a single plus sign. JavaScript's type coercion is one of those features that feels like a convenience when you're first learning—who doesn't love it when the language "just figures out" what you mean?—but in a professional codebase, it's a liability. When you let the engine guess your intent, you're essentially gambling that the engine's guess matches your logic.

The trap of the "helpful" plus sign

Imagine you're building a simple feature to calculate a shipping total. You're grabbing a value from an input field, which, as you know, always comes back as a string. A naive approach looks like this:

let subtotal = "29.99"; 
let shipping = 5.00;
let total = subtotal + shipping; 
// Result: "29.995"

It’s a classic mistake. Because the + operator is overloaded in JavaScript to handle both addition and string concatenation, the engine sees a string and says, "Oh, we must be building a sentence here," and just glues the numbers together. I've seen this happen in production environments where a price total suddenly becomes a massive string of digits, and the customer is very confused why their order costs twenty-nine dollars and ninety-nine cents... five.

Choosing explicit conversion over implicit guesses

The better way—the way I expect to see in any pull request I review—is to be loud and explicit about your intentions. Don't make the engine guess; tell it exactly what the data is. By using Number() or parseFloat(), you move the point of failure to the start of the operation rather than the end.

let subtotal = "29.99";
let shipping = 5.00;
let total = Number(subtotal) + shipping; 
// Result: 34.99

Now, the logic is bulletproof. If subtotal happens to be something completely wild—like the string "Free"—Number("Free") returns NaN. While NaN isn't a "pretty" result, it's infinitely better than "Free5" because it tells you immediately that your data is corrupt. I'd much rather have a program that crashes or logs an error than one that silently calculates the wrong price and charges a credit card for the wrong amount.

The danger of the loose equality check

This same philosophy applies to how we compare values. You'll see == (loose equality) in a lot of old tutorials, and it seems handy because it coerces types for you. For example, 0 == false is true, and "" == 0 is also true. In a small script, that's a shortcut. In a large application, that's a bug waiting to happen.

When you use === (strict equality), you're telling JavaScript: "These must be the same type AND the same value." If you're checking if a user's input is 0, you don't want a blank string to pass that test. By sticking to strict equality, you force yourself to handle your types correctly before the comparison happens. It adds one extra line of code for the conversion, but it saves you three hours of debugging on a Friday afternoon.




📋 Practical Task

Fixing the "Leaky Checkout Cart" Logic

You've inherited a piece of code for a shopping cart that is producing bizarre results. The current implementation relies entirely on implicit coercion, and it's causing the totals to be calculated as strings and the "Empty Cart" check to fail intermittently.

Your Task: Rewrite the calculateFinalPrice function. You must remove all loose equality checks (==) and ensure that all string inputs are explicitly converted to numbers before any arithmetic takes place. The function should return a proper number, not a string.

function calculateFinalPrice(cartTotal, taxRate, discountCode) {
    // BUGGY CODE:
    // 1. cartTotal is passed as a string (e.g., "100")
    // 2. taxRate is a number (e.g., 0.07)
    // 3. discountCode is either "10" (as a string) or null
    
    let total = cartTotal + (cartTotal * taxRate);
    
    if (discountCode == "10") {
        total = total - 10;
    }
    
    if (cartTotal == 0) {
        return 0;
    }

    return total;
}

// Test Case:
console.log(calculateFinalPrice("100", 0.07, "10")); 
// Current wrong output: "1007.0" (due to "100" + 7)
// Expected correct output: 97
Rating
0 0

There are no comments for now.

to be the first to leave a comment.