TypeScript Utility Types

Chapter Outline

Type Manipulation with Utility Types

TypeScript offers a powerful feature set for building robust applications, and one of the most versatile aspects of TypeScript is its ability to perform type manipulation using utility types. These built-in utility types provide flexible ways to transform types in your applications, enhancing reusability, maintainability, and scalability of your codebase. This article delves into several commonly used utility types, demonstrating their practical applications with examples.

What are Utility Types?

Utility types in TypeScript are a set of generic types defined in the language's standard library. They are used to transform existing types into new, modified types. This is particularly useful in complex applications where you need more control over the typing of variables without repeating type definitions, thus adhering to the DRY (Don't Repeat Yourself) principle.

Common Utility Types and Their Applications

Let’s explore some of the most commonly used utility types in TypeScript:

1. Partial<T>

The Partial<T> utility type takes a type T and makes all of its properties optional. This is useful when you want to create objects that do not include all the properties of the original type.

typescript
1interface User {
2 id: number;
3 name: string;
4 email: string;
5}
6
7function updateUser(id: number, changes: Partial<User>) {
8 // Imagine this function updates a user in the database
9}
10
11updateUser(1, { name: "John Doe" }); // Only update the name, leave other properties unchanged

2. Readonly<T>

Readonly<T> makes all properties of type T read-only, meaning the properties of an object cannot be reassigned.

typescript
1interface Task {
2 title: string;
3 description: string;
4}
5
6const task: Readonly<Task> = {
7 title: "Finish article",
8 description: "Complete the TypeScript article"
9};
10
11task.title = "Start a new article"; // Error: Cannot assign to 'title' because it is a read-only property

3. Record<K, T>

Record<K, T> creates a type with a set of properties K of type T. This is useful for objects that act as dictionaries.

typescript
1interface CatInfo {
2 age: number;
3 breed: string;
4}
5
6const cats: Record<string, CatInfo> = {
7 Felix: { age: 3, breed: "Tabby" },
8 Garfield: { age: 5, breed: "Persian" }
9};
10
11console.log(cats.Felix.breed); // Output: Tabby

4. Pick<T, K>

Pick<T, K> creates a type by picking the set of properties K from T. It is useful when you want to create a new type that only includes a subset of the properties of another type.

typescript
1interface Product {
2 id: number;
3 name: string;
4 price: number;
5 description: string;
6}
7
8type ProductPreview = Pick<Product, 'name' | 'price'>;
9
10const productPreview: ProductPreview = {
11 name: "Laptop",
12 price: 999
13};

5. Exclude<T, U>

Exclude<T, U> constructs a type by excluding from T all properties that are assignable to U.

typescript
1type AvailableDrinks = "Coffee" | "Tea" | "Orange Juice" | "Lemonade";
2type HotDrinks = Exclude<AvailableDrinks, "Orange Juice" | "Lemonade">;
3
4const myDrink: HotDrinks = "Coffee"; // Valid
5const coldDrink: HotDrinks = "Orange Juice"; // Invalid

6. ReturnType<T>

Obtains the return type of a function type. This is useful when you need to use the return type of a function elsewhere in your code.

typescript
1function getAge(): number {
2 return 30;
3}
4
5type Age = ReturnType<typeof getAge>; // number

7. Parameters<T>

Extracts the types of parameters from a function type as a tuple type.

typescript
1function greet(name: string, age: number): string {
2 return `Hello ${name}, you are ${age} years old.`;
3}
4
5type GreetParameters = Parameters<typeof greet>; // [string, number]

Conclusion

Utility types are a powerful feature in TypeScript for manipulating types in ways that enhance flexibility and reusability of your code. By leveraging utility types, developers can write more maintainable and robust applications, reducing errors and improving developer productivity.

For more detailed information and additional utility types, refer to the TypeScript Utility Types documentation. This resource provides a comprehensive overview and examples that can help you master type manipulation in TypeScript.

Feedback