← Back to list

Advanced (Sub)Types in TypeScript You Need to Know

Simplifying Complex Type Scenarios with TypeScript’s Advanced Features

Sumita Kevat in Canopas · 2024-08-15 09:39 · 701 claps · 4.4 min read
#typescript #advanced-typescript #interfaces #basic-typescript #web-development
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Advanced (Sub)Types in TypeScript You Need to Know

Simplifying Complex Type Scenarios with TypeScript’s Advanced Features

Image by Canopas

Image by Canopas

Exciting News! Our blog has a new home! 🚀

Introduction

I’ve long appreciated the basic types and interfaces that TypeScript offers. They provide invaluable type safety and code clarity. However, there are scenarios where TypeScript’s rigid nature can feel limiting — though this perception is often due to unfamiliarity with its more advanced features.

Consider a common User type:

interface User {
  id: number;
  name: string;
  email: string;
  phone: number;
}

Now, imagine these common use cases:

  1. Displaying a public profile without phone and ID
  2. Handling a user form submission without an ID
  3. Updating only the user’s name

Initially, you might think you need to define separate types for each scenario, raising concerns about code reusability. But fear not! TypeScript provides a powerful set of advanced types that can elevate your TypeScript skills and solve these challenges elegantly.

In this post, we’ll explore some of TypeScript’s most useful advanced types: Pick, Partial, Omit, and others. These utilities allow you to write more concise, flexible, and safer code. They're surprisingly easy to grasp and incredibly helpful when working with databases, API responses, or form submissions.

Sponsored

Small habits, practiced daily, are the stepping stones to remarkable transformations. Try out **Justly **and start building your habits today!

[embed]Justly: Habits, Goals, Journal Build a system for getting 1% better every day.justly.life

1. Pick<T, K>

Creating a Subset of Properties

Pick<T, K> creates a new type by selecting a set of properties K from the type T. It allows you to create a subset of an existing type.

When you need to work with only specific properties of a larger type, especially in API responses or form submissions you can use Pick.

Considering the above example, we can create two different types using the Pick from User as below.

type UserInfo = Pick<User, 'id' | 'name'>
type UserBasicInfo = Pick<User, 'name' | 'email'>

const user: UserInfo = {
  id: 1,
  name: "abc",
}

const userDetails: UserBasicInfo = {
  name: "abc",
  email: "abc@gmail.com",
}

2. Partial<T>

Making All Properties Optional

Partial<T> creates a new type with all properties of T set to optional.

When you want to update an object but don’t need to provide all properties, you can use Partial type. It is often used in PATCH API endpoints.

type PartialUser = Partial<User>

const user: PartialUser = {
  name: "abc",
}

3. Required<T>

Making All Properties Required

Required<T> creates a new type with all properties of T set to required, removing optional modifiers.

You can use Required, when you need to ensure all properties of an object are provided, often used in configuration objects or form submissions.

type FormUser = Required<User>

const user: FormUser = {
  id: 1,
  name: "abc",
  email: "abc@gmail.com",
  phone: 9999999999,
}

4. Readonly<T>

Creating Immutable Types

Readonly<T> creates a new type with all properties of T set to read-only.

When you want to create immutable data structures or prevent accidental modifications like database configuration, you can use Readonly .

Consider a DB configuration object:

interface DBConfig {
  host?: string;
  port?: number;
  username?: string;
  password?: string;
  database?: string;
}

class DatabaseConnector {
  connect(config: Readonly<AppConfig>) {
    console.log('Connecting to database with config:', config);
  }
}

5. Record<K, T>

Creating an Object Type with Specific Key-Value Pairs

Record<K, T> creates an object type whose property keys are K and values are T.

When you need to create a dictionary or map-like structure with specific key and value types like for adding roles and permission as below, Record will help you to simplify the structure.

type Role = 'admin' | 'user' | 'guest';
type Permissions = 'read' | 'write' | 'delete';
type RolePermissions = Record<Role, Permissions[]>;

const permissionMap: RolePermissions =
  { 
    admin: ['read', 'write', 'delete'], 
    user:  ['read', 'write'], 
    guest: ['read'] 
  }

6. Omit<T, K>

Excluding Specific Properties

When you want to create a new type by excluding certain properties from an existing type, you can use Omit.

Omit<T, K> creates a new type with all properties from T except those specified in K.

Considering you don’t want to show phone on the user’s profile, You can create a new type using Omit as below,

type ProfileUser = Omit<User, 'phone'>;

const user: ProfileUser = {
  id: 1,
  name: "abc",
  email: "abc@gmail.com",
}

7. Exclude<T, U>

Excluding specific members from union types

It is useful when the type is Union Type. Exclude<T, U> creates a type by excluding from T all union members that are assigned to U.

When you want to remove specific types from a union type you can use Exclude.

For example,

type AllowedTypes = string | number | boolean | null | undefined;

// remove null and undefined
type NonNullableTypes = Exclude<AllowedTypes, null | undefined>;

function processValue(value: NonNullableTypes) {
  console.log(`Processing value of type ${typeof value}:`, value);
}

processValue('Hello');
processValue(42);
processValue(true);

// Below would cause compile-time errors:
processValue(null);
processValue(undefined);

8. Extract<T, U>

Extracting specific members from union types

Extract<T, U> creates a type by extracting from T all union members that are assignable to U. It is the reverse of Exclude where you can ignore a given type.

Consider a scenario where you have a mix of data types and want to extract only the numeric types:

type MixedData = string | number | boolean | Date | { [key: string]: any };

type NumericData = Extract<MixedData, number>;

function processNumericData(data: NumericData) {
  console.log(`Processing numeric data: ${data}`);
}

processNumericData(42);

// Below would cause compile-time errors:
processNumericData('42');
processNumericData(true);
processNumericData(new Date());
processNumericData({});

9. NonNullable<T>

Excluding null and undefined

NonNullable<T> creates a type by excluding null and undefined from T.

You can use NonNullable when you want to ensure that a value is neither null nor undefined. It is often used in form validation or data processing.

type UserInput = string | number | null | undefined;

function processUserInput(input: NonNullable<UserInput>) {
  console.log(`Processing user input: ${input}`);
}

processUserInput('Hello');
processUserInput(42);

// Below would cause compile-time errors:
processUserInput(null);
processUserInput(undefined);

This blog post was originally published on **canopas.com.**

To read the full version, please visit **this blog.**

Similar Useful Blogs

[embed]How to Test CSS Font Loading API Using Jest How to Test CSS Font Loading API Using Jestcanopas.com

[embed]8 Advanced features of Typescript: A deeper dive into the language Advanced features of Typescriptcanopas.com

We’re Grateful to have you with us on this journey!

If you like what you read, be sure you won’t miss a chance to give 👏 👏👏 below — as a writer it means the world!

Please share your thoughts in the comments section below. Your input enriches our content and fuels our motivation to create more valuable and informative articles for you.

Follow **Canopas **to get updates on interesting articles!


메타데이터
post_id
9e1ba0ee4ba4
slug
advanced-sub-types-in-typescript-you-need-to-know-9e1ba0ee4ba4
url
https://medium.com/canopas/advanced-sub-types-in-typescript-you-need-to-know-9e1ba0ee4ba4
canonical_url
https://medium.com/canopas/advanced-sub-types-in-typescript-you-need-to-know-9e1ba0ee4ba4
author_url
https://medium.com/@cp-sumita-k
status
ok
fetched_at
2026-06-09 15:37:30