<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: codeQualityMonkey</title>
    <description>The latest articles on DEV Community by codeQualityMonkey (@codequalitymonkey).</description>
    <link>https://dev.to/codequalitymonkey</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199925%2F27e1f77e-5d81-4104-a755-e382148a286e.png</url>
      <title>DEV Community: codeQualityMonkey</title>
      <link>https://dev.to/codequalitymonkey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codequalitymonkey"/>
    <language>en</language>
    <item>
      <title>Are You Ready to Become the Rubber Duck?</title>
      <dc:creator>codeQualityMonkey</dc:creator>
      <pubDate>Fri, 13 Feb 2026 10:53:18 +0000</pubDate>
      <link>https://dev.to/codequalitymonkey/are-you-ready-to-become-the-rubber-duck-5b92</link>
      <guid>https://dev.to/codequalitymonkey/are-you-ready-to-become-the-rubber-duck-5b92</guid>
      <description>&lt;p&gt;Last summer I spent two weeks vibe-coding an app with Lovable. The result looked great in the demo. Under the hood, everything lived in a handful of bloated files, state scattered like confetti across components that probably shouldn't have existed. I closed the tab and went back to writing code the old way.&lt;/p&gt;

&lt;p&gt;That was the wrong lesson.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dismissal
&lt;/h2&gt;

&lt;p&gt;I think most developers went through some version of this. You try the shiny AI tool, it produces something that kind of works, the code makes you wince, and you walk away convinced that AI-assisted development is a toy. I did. I used Cursor for a while after that, but only for the safe stuff — utility functions, test scaffolding, things I could verify at a glance. I didn't trust it with anything that mattered.&lt;/p&gt;

&lt;p&gt;Then I started using Claude Code with custom skills — feeding it my architectural patterns, my naming conventions, the way I structure projects. And something shifted. The output stopped feeling like a stranger's code. It felt like mine, written by a junior developer who'd actually read the docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The flip
&lt;/h2&gt;

&lt;p&gt;Here's the thing nobody tells you about rubber duck debugging. The duck doesn't need to understand your code. You do. The act of explaining makes complexity visible — you hear yourself say something illogical and catch it before the words finish leaving your mouth.&lt;/p&gt;

&lt;p&gt;We've spent the last two years treating AI as our rubber duck. We explain what we want, the model generates something, and we learn from the sparring. Better model, better result.&lt;/p&gt;

&lt;p&gt;That relationship is flipping.&lt;/p&gt;

&lt;p&gt;The models are getting good enough that they don't need us to explain the problem — they need us to answer the questions they can't figure out alone. Where should this service live? Should we prioritize consistency or flexibility here? Is this abstraction earning its complexity? These aren't questions a non-developer can answer. They require years of watching systems grow, rot, and collapse under their own weight.&lt;/p&gt;

&lt;p&gt;The smarter you are, the better the AI performs. You've become the rubber duck.&lt;/p&gt;

&lt;h2&gt;
  
  
  The vibe-coding lesson
&lt;/h2&gt;

&lt;p&gt;There's a popular narrative that AI doesn't care about code quality. That architecture is a human vanity. That you can just vibe your way to a working product and let the machine figure out the details.&lt;/p&gt;

&lt;p&gt;Wrong.&lt;/p&gt;

&lt;p&gt;LLMs suffer under bad code quality exactly like humans do. Point an agent at a messy codebase and watch it fix one bug while introducing three new ones. The same tangled dependencies that confuse a junior developer confuse the model. It hallucinates connections between modules that shouldn't know about each other. It duplicates logic because it can't find the existing implementation buried in a 2000-line file.&lt;/p&gt;

&lt;p&gt;Clean code isn't about aesthetics anymore — it's about making your AI collaborators effective. Good naming, clear boundaries, small modules. The things we always said mattered but sometimes let slide when we were the only ones reading the code. Now there's a team of tireless agents navigating your codebase around the clock, and every shortcut you took becomes their stumbling block.&lt;/p&gt;

&lt;h2&gt;
  
  
  From production to direction
&lt;/h2&gt;

&lt;p&gt;We spent years grinding the skills that are now being commoditized. Syntax mastery. Writing components. Debugging line-by-line. The raw speed of cranking out code. These were the things that made you a "fast" developer, and fast developers got promoted.&lt;/p&gt;

&lt;p&gt;That ladder is dissolving.&lt;/p&gt;

&lt;p&gt;What compounds now is everything we used to call "soft" skills — the tech lead skills. Knowing what good looks like. System thinking. Asking the right questions. Deciding what to build, not just how to build it. The irony is that these skills were always more valuable. We just couldn't prove it because the bottleneck was production speed. Remove the bottleneck, and suddenly the person who can steer a system matters more than the person who can type one out.&lt;/p&gt;

&lt;p&gt;If you're a developer who spent ten years building intuition about what makes software resilient, what makes abstractions worth their cost, what makes teams ship without tripping over each other — those years weren't wasted. They were preparation for a role that didn't fully exist until now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fear underneath
&lt;/h2&gt;

&lt;p&gt;I hear the same thing from developers everywhere. "We spent years building skills that are no longer relevant." It's not usually said that bluntly. It shows up as skepticism toward the tools, as insistence that "real" developers don't need AI, as a quiet refusal to engage.&lt;/p&gt;

&lt;p&gt;I get it. The fear isn't irrational. But it's pointed at the wrong thing.&lt;/p&gt;

&lt;p&gt;Your skills aren't obsolete. They're applied differently. The developer who understood why a certain pattern fails at scale still understands that — and now has agents that can implement the alternative in minutes instead of days. The developer who could spot a leaky abstraction from a code review still spots it — and now the fix ships the same afternoon.&lt;/p&gt;

&lt;p&gt;What actually holds people back isn't a lack of technical skill. It's the fear of stepping away from what's comfortable. The fear of admitting that the thing you were great at — raw code production — is no longer the differentiator.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new differentiator
&lt;/h2&gt;

&lt;p&gt;Smarter human, better result. That's the equation now.&lt;/p&gt;

&lt;p&gt;Not "faster typist, better result." Not "more Stack Overflow answers memorized, better result." The developer who reads widely, thinks in systems, and can articulate why a decision matters — that developer gets more out of AI than someone who can write a React component from memory.&lt;/p&gt;

&lt;p&gt;So the question isn't whether AI will replace developers. It's whether you're ready to be the person the AI turns to when it gets stuck. Whether you're ready to sit on the other side of the desk, answer the hard questions, and steer a system you didn't write every line of.&lt;/p&gt;

&lt;p&gt;Are you ready to become the rubber duck?&lt;/p&gt;

</description>
      <category>llm</category>
      <category>softwareengineering</category>
      <category>ai</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Art of Decorating: Making Utility Functions Work for You in TypeScript</title>
      <dc:creator>codeQualityMonkey</dc:creator>
      <pubDate>Tue, 11 Mar 2025 10:09:52 +0000</pubDate>
      <link>https://dev.to/codequalitymonkey/the-art-of-decorating-making-utility-functions-work-for-you-in-typescript-fdl</link>
      <guid>https://dev.to/codequalitymonkey/the-art-of-decorating-making-utility-functions-work-for-you-in-typescript-fdl</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;In the React world, where object-oriented programming isn’t as prominent, and where methods that manipulate object state are less common, finding existing utility functions can sometimes feel like a treasure hunt.&lt;/p&gt;

&lt;p&gt;Even when I try to be consistent with naming conventions, I often find myself lost in a sea of &lt;code&gt;calculateTotalAmount&lt;/code&gt;, &lt;code&gt;getTotalAmount&lt;/code&gt;, and &lt;code&gt;calculateTotal&lt;/code&gt;. Multiply this problem by several developers—and frequent team rotations—and you get an exponentially growing mess.&lt;/p&gt;

&lt;p&gt;But don’t get me wrong, I &lt;em&gt;love&lt;/em&gt; a well-curated set of utility functions. Solving a problem means breaking it down into smaller problems, and those smaller problems often lead to reusable utilities. The goal? A solid arsenal of helper functions that make our codebase clean and efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Initial Solution: Decorating Objects
&lt;/h2&gt;

&lt;p&gt;The Decorator Pattern initially seemed like a great way to attach utility functions directly to JavaScript objects. In the app I was developing, domain objects were key players, and since they were usually served from the backend, decorating them in &lt;code&gt;transformResponse&lt;/code&gt; when using RTK-query seemed like a natural choice.&lt;/p&gt;

&lt;p&gt;To avoid issues with serialization, you can use &lt;code&gt;defineProperties&lt;/code&gt; and set the property &lt;code&gt;enumerable&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calculateSum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SomeObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... do something ...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createDecorator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SomeObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;calculateSum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;calculateSum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;enumerable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// This makes the property non-enumerable&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;InsuranceObjectDecorated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoratedObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Drawbacks
&lt;/h3&gt;

&lt;p&gt;While this approach gives us quick access to utilities, it comes with some major drawbacks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Redundancy&lt;/strong&gt; – You need to decorate the object on every endpoint that fetches it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type Confusion&lt;/strong&gt; – A decorated version introduces a new type, creating inconsistencies within the repo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autocomplete Woes&lt;/strong&gt; – TypeScript’s structural typing means that the decorated version is valid as the non-decorated version, but you lose autocomplete benefits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cascading Updates&lt;/strong&gt; – Updating types results in a ripple effect of changes throughout the codebase.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Better Approach: Functional Decoration
&lt;/h2&gt;

&lt;p&gt;I love having utility functions at my fingertips, but the drawbacks above were deal-breakers. So I took a step back and rethought the approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Principles:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No adding methods to objects.&lt;/li&gt;
&lt;li&gt;No sneaky prototype hacks.&lt;/li&gt;
&lt;li&gt;No changing method return or parameter types.&lt;/li&gt;
&lt;li&gt;Works with both primitives and objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of modifying objects, we wrap them in a utility layer only when needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TypeA&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;DecoratedTypeA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TypeB&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;DecoratedTypeB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isTypeA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;sumUp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;sumUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isTypeB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;findUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot decorate object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Function overloading
&lt;/h3&gt;

&lt;p&gt;Notice the stacked function signatures at the beginning. This is TypeScript’s &lt;strong&gt;function overloading&lt;/strong&gt; feature. Compare it to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TypeA&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;TypeB&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;DecoratedTypeA&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;DecoratedTypeB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the latter, your IDE won’t know whether it’s dealing with &lt;code&gt;DecoratedTypeA&lt;/code&gt; or &lt;code&gt;DecoratedTypeB&lt;/code&gt;, killing autocomplete. Function overloading ensures that TypeScript correctly infers the type based on the input.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use It
&lt;/h3&gt;

&lt;p&gt;Now, whenever you want to see what utility functions are available for a type, just wrap your object or primitive in the decorate function to enjoy all your wired-up utils being listed out by your autocomplete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yourObjectOrPrimitive&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;autocomplete&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding utils
&lt;/h3&gt;

&lt;p&gt;Wiring up new utils to existing types or even adding a new type is a breeze! Just follow the steps below as needed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Create a new Decorated type if you are adding a completely new type to the decorator&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TheNewTypeDecoratedType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Add your new utils to the decorated type&lt;/span&gt;
    &lt;span class="na"&gt;newUtil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;types&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Create a new typeguard if needed&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isTheNewType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;TheNewType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Add the new function signature with the type and its corresponding decorated type&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TheNewType&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;TheNewTypeDecoratedType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Add a new conditional if it is a new type being added to the decorator&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isTheNewType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Wire up your utils!&lt;/span&gt;
      &lt;span class="na"&gt;newUtil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;theUtilYouWantToAdd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;already&lt;/span&gt; &lt;span class="nx"&gt;added&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot decorate object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enhancing TypeScript with Template Literal Types
&lt;/h2&gt;

&lt;p&gt;One weakness of TypeScript is its &lt;strong&gt;structural typing&lt;/strong&gt;, meaning two types that look the same are considered the same. Consider this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript won’t complain if you pass a &lt;code&gt;UserId&lt;/code&gt; where an &lt;code&gt;ObjectId&lt;/code&gt; is expected because both are just &lt;code&gt;string&lt;/code&gt; under the hood. &lt;/p&gt;

&lt;p&gt;This is problematic on two levels. Nobody stops you if you accidentally pass &lt;code&gt;UserId&lt;/code&gt; as the first param, and &lt;code&gt;ObjectId&lt;/code&gt; as the second, and there is no way for you to write a type guard that can separate the two. I guess you can already see how this messes with my beloved decorator solution above! You want to get all the utils that deal with ObjectId, but instead, you would only get string functions...&lt;/p&gt;

&lt;p&gt;but wait, there is hope! Let me introduce you to ...&lt;/p&gt;

&lt;h3&gt;
  
  
  Template Literal Types
&lt;/h3&gt;

&lt;p&gt;By leveraging &lt;strong&gt;Template Literal Types&lt;/strong&gt;, we can create distinct, string-based types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`objectId-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can create type guards for runtime validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isObjectId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="sr"&gt;/^objectId-&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Combining with Decorate
&lt;/h3&gt;

&lt;p&gt;With this, we can extend our &lt;code&gt;decorate&lt;/code&gt; pattern to work on primitives and their intended type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objectId&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getObjectWorth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ObjectId&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;DecoratedObjectId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isObjectId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;getObjectWorth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getObjectWorth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot decorate object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By rethinking our approach to utility functions, we: ✅ Avoid modifying objects. ✅ Maintain strong TypeScript inference. ✅ Keep our utility functions accessible without messy type changes. ✅ Enhance runtime type safety with Template Literal Types.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;decorate&lt;/code&gt; function provides a clean and scalable way to attach utilities to objects without sacrificing readability, maintainability, or TypeScript’s powerful type inference.&lt;/p&gt;

&lt;p&gt;So, the next time you’re tempted to inject utility methods directly into objects—stop. Try a functional approach instead, and keep your codebase clean and predictable.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>frontend</category>
      <category>node</category>
      <category>react</category>
    </item>
  </channel>
</rss>
