8 Essential TypeScript Utility Types You Need to Know

In this blog, we are going to learn about different utility types that we have in typescript and how they help us on daily basis. Utility types in TypeScript are built-in tools that allow us to create new types by transforming existing types. In this blog, we are going to cover the 8 most used utility types.

  1. Partial<Type>: Partial changes all the properties of an object to an optional. This means that each property of the resulting type can either have the value of the original property or it will be undefined. Let's see one example.

     interface Course {
      id : string,
      name : string,
      author : string,
      isPaid : boolean
     }
    
     /* In above interface we have all the value required but with us   of partial we can make then optinal
     */
     // New type for the old course type
     type PartialCourse = Partial<Course> 
    
     // See this won't give any error as all the properies are optional
     // And will work fine even we don't have value of author
     let myCourse : PartialCourse = {
         id : '123',
         name : 'LOVE YOUR SELF',
         isPaid : false
     }
    
     console.log(myCourse); // { id: '123', name: 'LOVE YOUR SELF', isPaid: false }
    

    In this case, since the author property was not explicitly set, it is not present in the output of console.log(myCourse).

  2. Required<Type>: Required changes all the properties in the object to required. In simple terms it's the opposite of Partial with partial we make object keys optional and with Required type we make object keys required. Required sets each property to be non-optional. Let's see one example.

     // We will use same above interface in all example.
    
     interface Course {
      id : string,
      name : string,
      author? : string, // this will be converted to non-optional
      isPaid : boolean,
      price?: number // this will be converted to non-optional
     }
    
     // Now if you will use this RequiredCourse type then all the keys
     // that we have in Course will be non-optinal example we have 
     // price and author optional in Course interface but won't be optional in RequiredCourse
    
     type RequiredCourse = Required<Course>
    
     // Below one will give us error because we have not given any  values to author and price
     let myCourse : RequiredCourse = {
         id : '123',
         name : 'LOVE YOUR SELF',
         isPaid : false
     }
     // We don't write code with errors so lets write correct version
     let myCourse : RequiredCourse = {
         id : '123',
         name : 'LOVE YOUR SELF',
         author 'hitesh choudhary',
         isPaid : false,
         price : 399
     }
     // { id: '123', name: 'LOVE YOUR SELF', author: 'hitesh choudhary', isPaid: false, price: 399 }
     console.log(myCourse)
    
  3. ReadOnly<Type>: This one is the simplest one it simply converts all the properties of an object to read-only means we can not modify any of the properties of the newly created object.it prevents the properties from being reassigned or mutated. Let's see one example.

     interface Course {
       id: string;
       price: number;
     }
    
     type ReadonlyCourse = Readonly<Course>;
    
     let myCourse: ReadonlyCourse = {
       name: '123',
       price: 399,
     };
    
     // YOU WILL GET COMPILE TIME ERROR BECAUSE ALL THE PROPERTIES ARE
     // READONLY
     myCourse.id = '234'; // Error: Cannot assign to 'id' because it is a read-only property.
     myCourse.price = 40; // Error: Cannot assign to 'price' because it is a read-only property.
    
  4. Pick<Type, Keys>: The pick utility type is used to create a new type by selecting a subset of properties from an existing type. It allows you to create a new type with only the properties that you need, and ignore the rest. Given the example, you have a big course Object and you only want name and price, in that case, we can use pick with keys id, name and price let's understand with an example.

     // Adding few more properties to our course object
     interface Course {
       id: string;
       name: string;
       author?: string;
       isPaid: boolean;
       price?: number;
       language: string;
       difficulty: 'beginner' | 'intermediate' | 'advanced';
       duration: number;
       description?: string;
     }
    
     type CourseSummary = Pick<Course, 'id','name' | 'price'>;
    
     const myCourse: CourseSummary = {
       id: '123',
       name: 'Learn TypeScript',
       price: 399,
     };
    
     myCourse.language = 'John Doe'; // Error: Property 'language' does not exist on type 'CourseSummary'.
     myCourse.duration = 30; // Error: Property 'duration' does not exist on type 'CourseSummary'.
     myCourse.price = 100; // Okay it exist brother no worries
    
  5. Omit<Type, Keys>: Omit is another utility type in TypeScript that allows you to create a new type by omitting specific properties from an existing type. It's simply the opposite of Pick because in pick we were passing the keys that we wanted to have in the newly created object and in the case of Omit we will pass the keys that we don't need in that case newly created object we will have a new object without those keys. Let's see one example.

     interface Course {
       id: string;
       name: string;
       author: string;
       isPaid: boolean;
       price?: number;
     }
    
     type CourseWithoutPrice = Omit<Course, 'price' | 'author'>;
    
     const myCourse : CourseWithoutPrice = {
       id: '1',
       name: 'Intro to TypeScript',
       isPaid: true,
     };
     // We can not use price because we omitted price and author
     console.log(myCourse.price); //Property 'price' does not exist on type 'CourseWithoutPrice'.
    
  6. Record<Type, Keys>: Record<Type, keys> is a TypeScript utility type that allows you to define an object type with a specific set of keys and value types. It's a shortcut for creating an object type with a given key and value type, instead of writing out the entire object type definition yourself. Let's see one example.

     type Fruit = 'apple' | 'banana' | 'orange';
     type Price = number;
    
     const fruitPrices: Record<Fruit, Price> = {
       apple: 0.5,
       banana: 0.25,
       orange: 0.75,
     };
    
     console.log(fruitPrices.apple); // Output: 0.5
     console.log(fruitPrices.banana); // Output: 0.25
     console.log(fruitPrices.orange); // Output: 0.75
    
  7. Exclude<Type, ExcludedUnion>: This typescript utility is different than what we have learned till now because exclude has nothing to do with keys and values but rather it helps us to exclude the types. A simple example is if we have one type where we can have string | boolean | number but now we want to exclude the boolean type and we want our new type to be a string | number rather than string | boolean | number this behaviour we can achieve with exclude let's see in the example.

     type IntialTypes = string | number | boolean
     const value: Exclude<IntialTypes, boolean> = "Be humble"; // a boolean cannot be used here since Exclude removed it from the type.
    
  8. Extract<Type, ExtractUnion>: Extract is the opposite of exclude here we pass the union type that we want rather than we want to exclude given the example you have type string | number | boolean and we want only string and number in newly created union type that we can do it with the extract.

     type Shape = 'circle' | 'square' | 'triangle' | 'rectangle';
    
     type TwoDimensionalShape = Extract<Shape, 'circle' | 'square'>;
    
     // TwoDimensionalShape is now 'circle' | 'square'
    

    That's all about TypeScript Utility. Thank you for reading this quick guide on mastering TypeScript utility types. I hope this has provided you with a useful overview of these powerful tools for type manipulation and transformation. Happy coding!