DEV Community

Nabeel Noor
Nabeel Noor

Posted on

Essential TypeScript Utility Types

If you have used typescript in your project then there is a fair chance that you have come across a situation where you have to write 100s of types and it leads you to the thought can I reuse the types that I have already defined? At least I have once thought this until I have not heard about utility types in typescript. One of the excellent features of typescript that is basically there to solve this problem.

In this, we will discuss some essential and valuable utility types that you must know before jumping into the world of typescript.

  1. Partial
  2. Required
  3. Omit
  4. Pick
  5. Readonly
  6. Mutable
  7. ReturnType
  8. Parameter
  9. Awaited
  10. Non Nullable
  11. Exclude
  12. Extract

Partial

The Partial utility type in TypeScript allows you to create a new type that has all properties of the original Type, but with each property marked as optional. This means you can assign undefined or a value of the property's type to these optional properties. The Partial type is particularly useful when you want to define or manipulate objects where not all properties are required.

Here's an example that demonstrates the usage of Partial:


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

/**
* here we have to provide all properties, otherwise typescript will through on type checking as all attributes are mandatory
*/
const existingUser: User = {
  id: 1,
  name: "John Doe",
  email: "john@example.com",
  age: 30,
};

/**
* here we can skip any attribute because using the Partial utility, we inform typescript that all its attributes are optional
*/

const newUser: Partial<User> = {
  name: "Jane Smith",
  email: "jane@example.com",
};

/**
 * Partial<User>
 * {
 * id?: number | undefined;
 * name?: string | undefined;
 * email?: string | undefined;
 * age?: number | undefined;
 * }
 */
Enter fullscreen mode Exit fullscreen mode

Required

The Partial utility type in TypeScript allows you to create a new type that has all properties of the original Type, but with each property marked as optional. This means you can assign undefined or a value of the property's type to these optional properties. The Partial type is particularly useful when you want to define or manipulate objects where not all properties are required.

Here's an example that demonstrates the usage of Partial:


interface User {
  id?: number | undefined;
  name?: string | undefined;
  email?: string | undefined;
  age?: number | undefined;
}

/**
 * Here you have to provide all attributes b/c by using Require utility we have made all attributes of User interface compulsory
 */
const newUser: Required<User> = {
  id: 1,
  name: 'John Doe',
  email: 'john@example.com',
  age: 30,
};

/**
 * Required<User>
 * {
 * id number;
 * name string;
 * email string;
 * age number;
 * }
 */

Enter fullscreen mode Exit fullscreen mode

Omit

The Omit utility type in TypeScript allows you to create a new type that excludes specified properties from the original Type. This means you can create a new type that includes all properties of the original type except for the specified keys.

Here's an example that demonstrates the usage of Omit:


interface Book {
  id: number;
  author: string;
  title: string;
  category: string;
  description: string;
}

type BookPreview = Omit<Book, 'description' | 'category'>;

/**
 * type BookPreview = {
 *   id: number;
 *   author: string;
 *   title: string;
 * }
 */

Enter fullscreen mode Exit fullscreen mode

Pick

The Pick utility is exactly the opposite of Omit utility.The Pick utility type in TypeScript allows you to create a new type by selecting specific properties from an existing type. It helps you extract a subset of properties and create a new type with only those selected properties.

Here's an example that demonstrates the usage of Pick:

interface Book {
  id: number;
  author: string;
  title: string;
  category: string;
  description: string;
}

type BookPreview = Pick<Book, 'id' | 'author' | 'title'>;

/**
 * type BookPreview = {
 *   id: number;
 *   author: string;
 *   title: string;
 * }
 */

Enter fullscreen mode Exit fullscreen mode

Readonly

The Readonly utility type in TypeScript is used to create a new type where all properties of the original type are read-only. It makes every property in the type immutable, meaning they cannot be modified once assigned a value.

Here's an example that demonstrates the usage of Readonly:

interface Book {
  id: number;
  author: string;
  title: string;
  category: string;
  description: string;
}

type ReadOnlyBook = Readonly<Book>;

/**
 * type BookPreview = {
 *  readonly id: number;
 *  readonly author: string;
 *  readonly title: string;
 *  readonly category: string;
 *  readonly description: string;
 * }
 */

//if you don't provide all type then typescript will give error on type checking
const odacy: ReadOnlyBook = {
  id: 1,
  author: 'Ben',
  title: 'Odacy',
  category: '',
  description: '',
};

Enter fullscreen mode Exit fullscreen mode

Mutable

Now since we talk about readonly utility. There is also very useful helper function that use in typescript code base and that is Mutable.The Mutable utility type is not a built-in TypeScript utility type. However, you can create your own Mutable utility type to reverse the immutability of a type. It allows you to make the properties of a type mutable again, even if they were originally defined as read-only.

Here's an example of how you can create the Mutable utility type and use it:

interface ReadOnlyBook {
  readonly id: number;
  readonly author: string;
  readonly title: string;
  readonly category: string;
  readonly description: string;
}

type Mutable<T> = {
  -readonly [P in keyof T]: T[P];
};

const mutableBook: Mutable<ReadOnlyBook> = {
  id: 30,
  author: 'John Doe',
  title: 'odacy',
  category: 'novel',
  description: '....',
};

mutableBook.title = 'Jane Smith'; // Valid: 'name' is mutable
mutableBook.id = 40; // Valid: 'age' is mutable
Enter fullscreen mode Exit fullscreen mode

ReturnType

The ReturnType utility type is a built-in TypeScript utility type that extracts the return type of a function or constructor type.

Here's an example that demonstrates the usage of ReturnType:

interface Book {
  id: number;
  author: string;
  title: string;
  category: string;
  description: string;
}

const getAuthorName = (book: Book): string => {
  return book.author;
};

type author = ReturnType<typeof getAuthorName>;
/**
 * type author = string
 */

Enter fullscreen mode Exit fullscreen mode

Parameter

The Parameters utility type is a built-in TypeScript utility type that extracts the parameter types of a function type or constructor type as a tuple.

Here's an example that demonstrates the usage of Parameters:

interface Book {
  id: number;
  author: string;
  title: string;
  category: string;
  description: string;
}

const setAuthorName = (book: Book, authorName: string): Book => {
  book.author = authorName;
  return book;
};

type author = Parameters<typeof setAuthorName>;
// /**
//  * type author = [book: Book, authorName: string]
//  */
Enter fullscreen mode Exit fullscreen mode

Awaited

The Awaited utility type is a built-in TypeScript utility type that extracts the resolved type of a promise. It unwraps the generic type parameter of a Promise and gives us the actual type T.

Here's an example that demonstrates the usage of Awaited:

async function fetchData(): Promise<string> {
  return "Data fetched";
}

type FetchedData = Awaited<ReturnType<typeof fetchData>>;

async function printData(): Promise<void> {
  const data: FetchedData = await fetchData();
  console.log(data); // Output: Data fetched
}

printData();
Enter fullscreen mode Exit fullscreen mode

Non Nullable

NonNullabe utility type allow you to create new type from the existing one excluding the undefined and null from the existing one

Here’s an example that demonstrates the usage of NonNullable:

type Author = string | undefined | null;
type NonNullableAuthor = NonNullable<Author>;
Enter fullscreen mode Exit fullscreen mode

Exclude

The Exclude utility type in TypeScript creates a new type that excludes the types present in the union U from the union T. It essentially removes the common types between T and U.

Here's an example to illustrate the usage of Exclude:

type BookCategory =
  | 'fiction'
  | 'documentary'
  | 'mystery'
  | 'thriller'
  | 'comedy';
type SuspenseCategory = 'thriller' | 'mystery';

type NonSuspenseCategory = Exclude<BookCategory, SuspenseCategory>;

/**
 * type NonSuspenseCategory = "fiction" | "documentary" | "comedy"
 */

Enter fullscreen mode Exit fullscreen mode

Extract

The Extract utility is exactly the opposite of Exclude utility. The Extract utility type in TypeScript allows you to create a new type by extracting specific members from a union type.

Here's an example to illustrate the usage of Extract

type BookCategory =
  | 'fiction'
  | 'documentary'
  | 'mystery'
  | 'thriller'
  | 'comedy';
type SuspenseCategory = Extract<BookCategory, 'thriller' | 'mystery'>;

/**
 * type SuspenseCategory = "mystery" | "thriller"
 */

Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
nabeelnoor profile image
Nabeel Noor • Edited

Feel free to drop question if you have any confusion,I'll do my best to answer it

Collapse
 
ahmadmustafaan1 profile image
Ahmad Mustafa Anis

Great overview of essential TypeScript utility types! They provide powerful tools for manipulating and enhancing types, making code more efficient and reusable. Keep up the good work!