myHotTake

Tag: type checking

  • How Does TypeScript Enhance Your JavaScript Journey?

    If you find this analogy helpful, feel free to like or share it!


    I’m embarking on a road trip with my team and our trusty old car, JavaScript. It’s been reliable, but as our journey grows more complex, we decide it’s time to upgrade to a new vehicle, TypeScript, which promises more safety features and a smoother ride. Now, teaching my team TypeScript best practices during this migration feels like guiding them on how to drive this new car efficiently.

    I start by explaining the car’s new dashboard. While JavaScript had simple indicators, TypeScript offers a sophisticated dashboard with alerts for potential issues ahead—much like TypeScript’s type-checking that warns us of bugs before they become problems.

    Next, I introduce them to the car’s GPS system. In JavaScript, we sometimes found ourselves lost or taking wrong turns. TypeScript’s GPS is like its powerful tooling and IntelliSense, guiding us precisely on our coding path, suggesting turns (or code improvements) we might not see otherwise.

    I also highlight the importance of understanding the car’s different fuel types. While JavaScript could run on anything, TypeScript requires us to use specific types of fuel—analogous to understanding and using types properly to ensure optimal performance.

    As we drive, I emphasize the car’s safety features, like lane assist and blind-spot monitoring. These are akin to TypeScript’s strict null checks and type guards, keeping us on track and preventing crashes in our code.

    Lastly, I remind them that even the best cars need regular maintenance. Similarly, keeping our TypeScript knowledge up-to-date ensures we’re using it to its full potential, much like keeping our new car running smoothly throughout our journey.

    Through this road trip, my team learns to appreciate TypeScript’s features and benefits, making our migration not just a change of vehicle, but an exciting upgrade to our coding journey.


    Now we’re driving along a familiar route, but now with our new TypeScript car. We encounter a section of the road where we used to rely solely on intuition—JavaScript’s dynamic typing. In JavaScript, we might have had a function like this:

    function greet(name) {
      return "Hello, " + name;
    }
    
    console.log(greet("Alice")); // "Hello, Alice"
    console.log(greet(42)); // "Hello, 42"

    In our old car, we’d sometimes end up with unexpected results. Our TypeScript vehicle, however, comes with a feature that helps us avoid these surprises by clearly marking the lanes we should drive in:

    function greet(name: string): string {
      return "Hello, " + name;
    }
    
    // console.log(greet("Alice")); // "Hello, Alice"
    // console.log(greet(42)); // Error: Argument of type 'number' is not assignable to parameter of type 'string'.

    Here, TypeScript’s type system ensures we’re using the right type of “fuel,” preventing us from making the wrong turn.

    Next, we encounter a foggy stretch of road where visibility is low. In JavaScript, we might write code that assumes certain values are always present:

    function getLength(str) {
      return str.length;
    }
    
    console.log(getLength("Hello")); // 5
    console.log(getLength()); // Error

    Our TypeScript car, however, is equipped with fog lights—null and undefined checks:

    function getLength(str?: string): number {
      return str ? str.length : 0;
    }
    
    console.log(getLength("Hello")); // 5
    console.log(getLength()); // 0

    This safety feature ensures we don’t hit unexpected roadblocks.

    Finally, we approach a junction where we need to decide which path to take. In JavaScript, we might have used loose equality, leading to potential misdirections:

    console.log(0 == false); // true
    console.log("0" == 0); // true

    TypeScript helps us stay on the right path with strict equality checks, much like clear road signs:

    console.log(0 === false); // false
    console.log("0" === 0); // false

    Key Takeaways:

    1. Type Safety: TypeScript helps prevent common mistakes by enforcing types, akin to ensuring we use the right fuel.
    2. Error Prevention: It provides tools for handling potential errors, much like safety features in our car.
    3. Code Clarity: With TypeScript, our code becomes clearer and more predictable, similar to using strict road signs.
  • How Do Custom Type Guards Enhance TypeScript Safety?

    If you enjoyed this story and find it helpful, feel free to like or share it with others who might benefit!


    I’m a superhero with a unique ability: I can see through disguises. In the world of TypeScript, everything is an object, and sometimes these objects wear masks, pretending to be something they’re not. My mission is to unmask them and reveal their true identities. This is where my power, which I call a “custom type guard,” comes into play.

    In this world, we have different creatures, like “Cats” and “Dogs,” each with distinct traits. A Cat might have a “meow” method, while a Dog might have a “bark” method. However, in this world, some creatures are sneaky and like to pretend they’re something they’re not. I need to ensure that if I’m talking to a Cat, it’s truly a Cat.

    So, how do I use my superpower? Picture me holding a special magnifying glass that can reveal the truth. When a creature approaches me, I hold up my magnifying glass and look for specific traits. If I see a “meow” method, I proclaim, “Aha! This is indeed a Cat!” This process is my custom type guard in action.

    To create one of these magnifying glasses, or custom type guards, I define a function. Let’s say I call it isCat. This function takes a creature as an argument and checks for the presence of the “meow” method. If it’s there, my magnifying glass glows, confirming the creature is a Cat. I can then confidently interact with it, knowing it won’t suddenly start barking like a Dog.

    In this way, my custom type guards help me navigate this world with certainty, ensuring that I’m always aware of the true nature of the creatures I encounter. It’s a bit like being a detective with a supernatural tool, always ready to uncover the truth behind the mask.


    Continuing from where I left off, my magnifying glass is actually a TypeScript function that acts as a custom type guard. Here’s how I craft it in code to ensure I’m dealing with a Cat and not a mysterious imposter:

    interface Cat {
      meow: () => void;
    }
    
    interface Dog {
      bark: () => void;
    }
    
    // Here's my magnifying glass, or custom type guard function
    function isCat(creature: any): creature is Cat {
      return (creature as Cat).meow !== undefined;
    }
    
    // Now, let's see it in action with some creatures
    const unknownCreature1 = { meow: () => console.log("Meow!") };
    const unknownCreature2 = { bark: () => console.log("Woof!") };
    
    if (isCat(unknownCreature1)) {
      unknownCreature1.meow(); // Confidently call meow because I know it's a Cat
    } else {
      console.log("This is not a Cat.");
    }
    
    if (isCat(unknownCreature2)) {
      unknownCreature2.meow(); // This won't run because it's not a Cat
    } else {
      console.log("This is not a Cat.");
    }

    In this code, I create a function isCat that checks if the meow method is present, which is my way of exposing the true identity of the creature. This function returns a boolean, but it also informs TypeScript that if the function returns true, the type of the argument can safely be treated as a Cat.

    Key Takeaways:

    1. Custom Type Guards: They are functions that help TypeScript infer more specific types based on runtime checks. They use the syntax creature is Cat to refine types.
    2. Type Safety: By using custom type guards, we can safely access properties or methods specific to a type without risking runtime errors.
    3. Flexibility: Custom type guards provide flexibility in handling objects whose types may not be immediately apparent, especially in dynamic or loosely typed data scenarios.
    4. Efficiency: They allow us to write code that’s both efficient and expressive, leveraging TypeScript’s type system to manage complex data interactions.