DEV Community

Cover image for Stop Using “?” Everywhere! Use `Omit` ( i.e. Utility Types) for Safer TypeScript
Hossain MD Athar
Hossain MD Athar

Posted on

Stop Using “?” Everywhere! Use `Omit` ( i.e. Utility Types) for Safer TypeScript

TypeScript was created for one purpose: to bring safety and clarity to JavaScript. When Microsoft first released it, their mission was simple - give developers predictable types, reduce runtime bugs, and make debugging easier.

But even with all the guardrails TypeScript provides, there’s one tiny operator that many developers misuse without realizing the long-term cost:

? — the optional modifier.

It looks harmless. It’s convenient. But using it in the wrong places quietly destroys the type safety TypeScript was built for.

Let’s talk about why — with real-world examples, better patterns, and official TS-backed solutions.

Where Things Start to Go Wrong

Imagine a simple model:

type User = {
  id: string;
  name: string;
  email: string;
};
Enter fullscreen mode Exit fullscreen mode

A User always has an ID.
This is part of your domain logic. The backend guarantees it.

But when you’re building a form to create a user, you don’t have an id yet. And this is where many developers introduce a subtle bug:

id?: string;
Enter fullscreen mode Exit fullscreen mode

Looks tiny, but this changes everything. Because now, TypeScript thinks:

  • A user might have an ID
  • Or might not
  • Anywhere in the entire codebase

Your core type becomes weaker, and the compiler loses its ability to actually protect you.

Real Life Example: When TS Yells at You

Let me show you how this problem shows up at work. I had code like this:

const customerId = client.customerId;
const updatedData = await updateCustomerById({ id: customerId, body: data }).unwrap();
Enter fullscreen mode Exit fullscreen mode

Nothing looks wrong…
But TypeScript hits you with this:

'client' is possibly 'undefined'.ts(*****)
Enter fullscreen mode Exit fullscreen mode

Why?
Because somewhere in the type definitions, someone got lazy and wrote:

type Client = {
  customerId?: number;
  ... 
};
Enter fullscreen mode Exit fullscreen mode

That one little ? forces TypeScript to assume:

  • client.customerId might be undefined
  • and you must guard every line of code

So you end up writing completely unnecessary defensive code:

if (!client?.id) throw new Error("Client id missing!");
// or maybe, you add condition in submit function 
Enter fullscreen mode Exit fullscreen mode

The real problem is the type design, not the logic.

The Fix the TypeScript Docs Recommend

TypeScript’s official documentation gives us tools for this exact situation.

TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally. [TS docs]

The solution is not to make everything optional.

The solution is to derive specific types for specific contexts using utility types.

Use Omit — Not ?

If a User always has an ID, but your form doesn’t, you create a separate type:

type CreateUserInput = Omit<User, "id">;
Enter fullscreen mode Exit fullscreen mode

Done.
Clean.
Safe.
Predictable.

Your domain stays strict:

type User = {
  id: number;
  name: string;
  email: string;
};
Enter fullscreen mode Exit fullscreen mode

This is exactly what TypeScript recommends in its documentation on building new types from existing ones.

Final Thoughts

The next time you feel the urge to sprinkle ? everywhere to make TS stop complaining, pause a moment and ask:

“Am I modeling reality… or am I just silencing TypeScript?”

Use Omit, Pick, and TypeScript’s built-in utilities. Your future self — and TypeScript — will thank you. Explore more and comment below how utility types saved you!

Top comments (0)