40.8 TypeScript Style Guides: Google, Airbnb, and Community Standards

Right, so you’ve decided to write some TypeScript that doesn’t look like it was generated by a room full of cats walking on keyboards. Good. The first step is admitting you have a problem. The second step is realizing that while your personal style is fascinating, it’s also a nightmare for anyone else who has to read your code. This is where style guides come in. They’re the guardrails that keep you from driving your beautifully typed code off a cliff of inconsistency.

40.7 Keeping Types DRY: When to Extract and When to Inline

Look, we need to talk about your types. I’ve seen the code. The sprawling, 20-property interfaces defined in-line for a single function argument. The string literals copy-pasted across seven different files. It’s a maintenance nightmare waiting to happen, and I’m here to be your nightmare-intervention friend. The principle of DRY—Don’t Repeat Yourself—isn’t just for your logic. It’s absolutely critical for your type definitions. A change in one part of your data model should ripple through your entire codebase correctly, courtesy of the TypeScript compiler, not force you on a bloody safari to hunt down every duplicate definition. The compiler is your friend, your ally, your incredibly pedantic robotic code-reviewer. Use it.

40.6 Function Overloads vs Union Parameter Types

Right, so you’ve hit the point where you need a function to handle a few different flavors of input. Your first, perfectly reasonable instinct might be to reach for a union type. Let’s say you want a function that can format either a Date object or a UNIX timestamp (which is a number). function formatTimestamp(input: Date | number): string { if (input instanceof Date) { return input.toISOString(); } else { return new Date(input).toISOString(); } } This works. It’s clear, and TypeScript is happy because we’ve narrowed the type inside the function. But what if the output type also changes based on the input? What if you want to return a string for a Date input, but a number (maybe the raw timestamp) for a number input? Your union approach just blew up in your face. The return type would have to be string | number, which is probably a nightmare for whoever calls your function.

40.5 Enums vs Const Assertions vs Union of Literals: Choosing Wisely

Right, let’s settle this. You’ve got a value that can only be a few specific things. Maybe it’s the status of an API request: 'idle', 'loading', 'success', 'error'. Your first instinct is to reach for a tool to enforce this. In TypeScript, you’ve got three main contenders, and the classic enum is often the wrongest choice. Let’s break down why. The Classic Enum: Often the Worst Choice You come from another language, you see enum, you think, “Aha! A known quantity.” TypeScript eagerly awaits to disappoint you. Behold the “ambient authority” of the classic enum:

40.4 Common Pitfalls: Mutating a Readonly Object, any Spreading

Right, let’s talk about one of those TypeScript gotchas that feels like the language is politely handing you a lit firecracker. You’ve probably slapped a readonly modifier on an array or object, feeling good about yourself for writing safe, immutable code. Good for you. Then, you do something perfectly reasonable like spreading it into a new object… and everything explodes. Or, more accurately, it doesn’t explode, and that’s the whole problem.

40.3 Don't Fight the Type System: Working With Inference

Look, I get it. You’re a smart developer. You see a variable and your first instinct is to tell the compiler exactly what it is. You reach for that trusty colon and type out const name: string = 'Bob'; like a responsible adult. It feels safe. It feels explicit. It feels… redundant. Because my friend, you just wrote a string literal to a const and then told TypeScript, the tool whose entire job is to infer types, that it’s a string. You’ve become the human equivalent of a // This is a comment comment.

40.2 Avoid Overusing any: Strategies for Incremental Typing

Look, we’ve all been there. You’re wrestling with a piece of JavaScript that’s more tangled than last year’s Christmas lights. The deadline is looming, and the siren song of any is calling: “Just one little any and all this pain will go away.” I get it. But using any is like putting a “Bugs Here!” sign on your code. It defeats the entire purpose of using TypeScript. You’re just writing verbose JavaScript at that point.

40.1 Prefer Interfaces for Public API, Type Aliases for Complex Compositions

Right, let’s settle this. You’ve probably seen interface and type used seemingly interchangeably all over the place, and for simple object shapes, they basically are. But they’re not the same tool, and using them correctly is a mark of someone who knows their stuff. The golden rule I live by, and the one that will save you from future headaches, is this: Use interface for anything that forms the public contract of your code (especially for object inheritance), and use type for complex compositions, unions, and mappings.

— joke —

...