Skip to main content

Making Typing Simple In Typescript

· 3 min read
Sivabharathy

TypeScript is a powerful tool for enhancing JavaScript with strong typing. But like any tool, it can be misused. A common anti-pattern in TypeScript is duplicating types instead of leveraging its utility types. This leads to bloated, harder-to-maintain code.

Let’s explore this with an example and how to improve it by "typing smartly."


The Problem: Duplicating Types

Consider this "bad" approach (as shown in the image):

type User = {
id: number;
name: string;
email: string;
};

type UserPreview = {
id: number;
name: string;
};

type UserEdit = {
id: number;
name: string;
isAdmin: boolean;
};

What's wrong here?

  • Repetition: Fields like id and name are repeated.
  • Scalability issues: If the User type changes, all dependent types must be updated manually.
  • Prone to bugs: Easy to forget updating one of the derived types.

The Solution: Utility Types to the Rescue

TypeScript provides built-in utility types that help us avoid redundancy and keep types consistent.

Here’s a better approach:

type User = {
id: number;
name: string;
email: string;
};

type UserPreview = Pick<User, "id" | "name">;
type UserEdit = Omit<User, "id" | "email"> & { isAdmin: boolean };
type UserOptional = Partial<User>;

Let’s break it down

Pick<Type, Keys>

Create a new type by selecting a subset of properties.

type UserPreview = Pick<User, "id" | "name">;

Omit<Type, Keys>

Create a new type by excluding certain properties.

type UserEdit = Omit<User, "id" | "email"> & { isAdmin: boolean };

Partial<Type>

Make all properties optional.

type UserOptional = Partial<User>;

Bonus Examples

Let’s look at a few more real-world patterns where this approach shines.

1. Product Management

type Product = {
id: string;
title: string;
description: string;
price: number;
createdAt: Date;
};

type ProductCard = Pick<Product, "id" | "title" | "price">;
type ProductUpdate = Partial<Omit<Product, "id" | "createdAt">>;

2. Blog System

type Blog = {
id: number;
title: string;
content: string;
author: string;
tags: string[];
};

type BlogSummary = Pick<Blog, "id" | "title" | "tags">;
type BlogForm = Partial<Omit<Blog, "id">>;

Clean Code Benefits

  • 🔁 DRY (Don't Repeat Yourself)
  • 📦 Reusable components
  • 🔍 Easy Refactoring
  • 🧪 Consistent Typing
  • 🚀 Faster development

💡 Pro Tip: Combine Utility Types

You can also compose utility types for more control:

type EditableUser = Partial<Pick<User, "name" | "email">>;

This gives you a type where only name and email are optional — not the full User.


🛠️ Custom Utility Types

If you find yourself repeating patterns, you can even write your own utility types:

type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

type CustomEditUser = Without<User, "email">;

🏁 Final Thoughts

Using TypeScript utility types like Pick, Omit, and Partial isn’t just a trick — it’s a best practice. It helps you write concise, safe, and easily maintainable code.

Next time you feel like copying and tweaking a type, stop. Think: Can I simplify this with a utility type? Most likely, the answer is yes.


✨ Stay DRY, Stay Typed.

If you liked this post, share it with your TypeScript squad!