myHotTake

Tag: TypeScript flexibility

  • How Do Mapped Types Enhance Flexibility in TypeScript?

    If you enjoy this story and find it helpful, feel free to give it a like or share it with others who might appreciate it too!


    I’m a costume designer, and I specialize in crafting custom outfits for a wide variety of clients. Each client comes to me with a specific list of requirements, like the type of fabric, color, and style they want for their outfit. Now, in order to keep my workflow efficient, I’ve developed a special technique that allows me to quickly convert these requirements into the perfect pattern for each client.

    In the world of TypeScript, this special technique is similar to what we call “mapped types.” Picture a mapped type as my tailoring pattern that can take the requirements for any outfit and transform them into a ready-to-sew pattern. It’s like I have a universal pattern template, and all I need to do is feed in the specific details for each client. The magic happens when I use a “key” from a client’s requirements to map out the exact pattern pieces I need.

    For instance, suppose a client wants a jacket with specific sleeve length and pocket style. I take my base pattern and, using the mapped type, I adjust the sleeve length and pocket style according to the keys provided in the client’s list. This way, I don’t have to reinvent the pattern for each client; I simply adapt my universal pattern using their specific instructions.

    This technique not only saves me time but also ensures that each outfit is precisely tailored to fit the client’s needs. In TypeScript, mapped types allow me to do the same thing with my code, taking an object type and creating a new type by transforming its properties according to a specific set of rules. It’s my way of ensuring that every piece of code fits just right, just like how every outfit I create is perfectly tailored to each client.

    So, as I continue crafting custom outfits in my marketplace, I lean on the power of mapped types to keep my tailoring process seamless and adaptable, ensuring every client walks away with a perfect fit.


    I have a base pattern for outfits, defined as a TypeScript interface:

    interface OutfitRequirements {
      sleeveLength: string;
      pocketStyle: string;
      fabricType: string;
    }

    This is like a checklist for each client’s requirements. Now, suppose I want to create a new pattern that marks each requirement as optional for some clients who want a more flexible outfit design. In my tailoring shop, this is akin to having a base pattern where I can choose to include or exclude certain features. Here’s how I can use a mapped type to achieve this:

    type FlexibleOutfit = {
      [Key in keyof OutfitRequirements]?: OutfitRequirements[Key];
    };

    In this code snippet, FlexibleOutfit is a mapped type that takes each key from OutfitRequirements and makes it optional using the ? modifier. This is like saying, “For this particular client, I might or might not include the sleeves or pockets, depending on their preference.”

    Now, let’s say I want to ensure that all the properties are read-only, so once the outfit is designed, it can’t be altered. I can create a mapped type for that too:

    type ReadOnlyOutfit = {
      readonly [Key in keyof OutfitRequirements]: OutfitRequirements[Key];
    };

    With ReadOnlyOutfit, every property is locked in place, just like a completed outfit that’s ready for delivery and can’t be modified.

    Key Takeaways:

    1. Mapped Types as Tailoring Patterns: Mapped types allow me to transform existing types in TypeScript, similar to how I adapt my base patterns for different clients in my tailor shop.
    2. Customization and Flexibility: By using mapped types, I can create flexible and adaptable type definitions, such as optional or read-only properties, to suit different coding needs.
    3. Efficiency and Precision: Just as my tailoring process becomes more efficient and precise with mapped types, so does my coding, as it reduces redundancy and enhances type safety.
  • How Do Intersection Types Enhance JavaScript Flexibility?

    If you enjoy this story and find it helpful, feel free to like or share it with anyone who might appreciate a fresh take on JavaScript concepts!


    I have a toolbox that lets me build anything I can dream of. This isn’t just any ordinary toolbox; it contains tools that can morph and combine to suit any project needs. In this world, I often encounter varied and complex projects that need a mix of different tools to get the job done. This is where intersection types come into play.

    One day, I’m tasked with building a special kind of vehicle—let’s call it a “carcycle.” It needs to have the speed of a sports car and the maneuverability of a bicycle. Initially, I think of using either a car tool or a bicycle tool from my toolbox. But then I realize that neither tool alone is sufficient for this unique project.

    In my toolbox, I have a special function called an intersection tool. This tool allows me to blend the capabilities of the car tool and the bicycle tool into one. When I use the intersection tool, it combines the speed feature of the car with the maneuverability feature of the bicycle, giving me a hybrid tool that can construct the perfect “carcycle.”

    As I start working, I realize just how powerful this intersection tool is. It doesn’t just create a mere sum of parts; it crafts an entirely new tool that embodies the best aspects of both the car and the bicycle. This is the essence of intersection types in JavaScript—bringing together the strengths of multiple types to create a new, versatile type that can handle more complex scenarios than any single type could.

    By the end of my project, I’ve constructed a vehicle that is both fast and agile, thanks to the power of my intersection tool. Just like in JavaScript, where intersection types combine different type properties to create something new, my toolbox allows me to blend and build beyond the ordinary.


    Let’s see how this works in code:

    // Define two interfaces: Car and Bicycle
    interface Car {
      speed: number;
      drive(): void;
    }
    
    interface Bicycle {
      maneuverability: string;
      pedal(): void;
    }
    
    // Use an intersection type to combine both Car and Bicycle
    type Carcycle = Car & Bicycle;
    
    // Implement a function that takes a Carcycle
    function buildCarcycle(vehicle: Carcycle) {
      console.log(`Speed: ${vehicle.speed}`);
      console.log(`Maneuverability: ${vehicle.maneuverability}`);
      vehicle.drive();
      vehicle.pedal();
    }
    
    // Create an object that satisfies both Car and Bicycle interfaces
    const myCarcycle: Carcycle = {
      speed: 100,
      maneuverability: "high",
      drive: () => console.log("Driving fast!"),
      pedal: () => console.log("Pedaling smoothly!")
    };
    
    // Use the buildCarcycle function
    buildCarcycle(myCarcycle);

    In this example, the Carcycle type is an intersection of the Car and Bicycle interfaces. This means any object of type Carcycle must have all the properties and methods of both Car and Bicycle. The buildCarcycle function demonstrates how we can use such an object, leveraging both speed and maneuverability, just like our “carcycle.”

    Key Takeaways

    1. Intersection Types: In TypeScript, intersection types (&) allow us to combine multiple types into one, requiring objects to have all the properties and methods of the combined types.
    2. Versatile Objects: By using intersection types, we can create objects that capture the essence of multiple entities, making our code more flexible and powerful.
    3. Real-World Application: Just as a toolbox can combine tools for complex projects, intersection types help us handle complex data structures and requirements in our applications.