Jan 4, 2023

Typescript: Utility Types

Typescript comes with some handy utility types. In this blog, we will be exploring exactly that.
Ponikar Darshan Janardan
Ponikar Darshan JanardanSoftware Engineer - I
lines

Developers frequently claim that typescript requires them to write redundant code. The reasons can vary, but one of the most common is a failure to use utility types.

Types are analogous to utility functions in Javascript.

They are provided in typescript to make our lives easier. Let's take a look at them one at a time.

1. Partial

Partial<T> allows you to create optional props with a single line of code. Without it, we'd need to duplicate the User type, which isn't ideal.

type User = {
     name: string;
     password: string;
}

// redundant codes
type OptionalUserProps = {
    name?: string;
    password?: string;
}

Below is an example of Partial utility type.

type OptionalUsersProps = Partial<User>

Partial takes type as an argument.

2. Required

Required<T> is the inverse of Partial. It creates all the necessary props.

type Fish {
      name: string;
      food?: string[];
      origin?: string;
}

// all the props are required.
type RequiredFish = Required<Fish>

Required also takes type as an argument.

3. Readonly

In JavaScript, readonly functions similarly to const. You cannot reassign a type once it has been marked as readonly.

type Currency = {
 America: "USD";
 India: "INR";
 France: "Euro";
}

type ReadOnlyCurrency = Readonly<Currency>;

4. NonNullable

NonNullable<T> filters your type and removes null and undefined from the union of types.

// gender will have male and female type.
type Gender = NonNullable<"male" | "female" | null | undefined>;

5. Exclude

Exclude<T, K> lets you remove type from the union types.

type Languages = "Java" | "JavaScript" | "TypeScript";

// Excluding Java from union type.
type MyFavLang = Exclude<Languages, "Java">;

// passing union type.
type TypeScriptOnly = Exclude<Languages, "Java" | "JavaScript">

It takes two arguments. The first is type, while the second is a union of props.

6. Extract

Extract<T, K> is the inverse of Exclude. It will generate union types based on the specified union type.

type Languages = "Java" | "JavaScript" | "TypeScript";

// Extract TypeScript and JavaScript from Languages.
type MyFavLang = Extract<Languages, "TypeScript" | "JavaScript">;

7. Pick

Pick<T, K> picks props from type. It will give you a new type.

type Car {
     engine: Engine;
     wheels: Wheels;
     color: "red" | "white" | "black";
     speed: number;
}

// selecting engine and wheels only.
type CarService = Pick<Car, "engine" | "wheels">

8. Omit

Omit<T, K> removes props from types.

type NewUser = {
     name: string;
     username: string;
     password: number;
     confirmPassword: number;
}

// password and confirmPassword will be removed
type User = Omit<NewUser, "password", "confirmPassword">

9. ReturnType

ReturnType<T> gives return type of function.

// Type T can be string or number
type T = ReturnType<() => string | number>

10. Record

Record<T, K>creates an object type.

Instead of doing this:

type SpaceShip = {
   [k :string]: number;
}

You can do this:

type SpaceShip = Record<string, number>

const spaceship: SpaceShip = {
   name: "StarShip",
   color: "Red",
   speed: "High"
}

// You can pass union type as key as well.
type Num = Record<string | number, number>

const numbers :Num = {
  first: 1,
  2: 2,
  three: 3
}

Record also accepts union type as key that is not supported by interface and type.

As we can see, utility types help in avoiding redundancy in the codebase. It also enables maintaining a single source of truth.

That's it for today. I hope you enjoyed this blog. Stay tuned for upcoming blogs on the typescript.

Hire our Development experts.