binaryhub.io
  • Home
  • Categories
    • Javascript
    • Typescript
    • Serverless
    • AWS (Amazon Web Services)
    • Docker
    • Linux
    • DevOps
    • IDE
  • About
  • Contact
No Result
View All Result
Your Coding Hub
No Result
View All Result
Home Typescript

Typescript Utility Types you must know – Pick, Omit, Partial, Record + BONUS TIP

Florin Mateescu by Florin Mateescu
December 17, 2022
in Typescript
Reading Time: 7 mins read
4
0
utility types typescript pick, omit, record,partial
322
VIEWS
Share on TwitterShare on LinkedInShare on Reddit

If you are working with Typescript you must know what utility types are and how much value they bring.

Stay with me in this article as we will go through Pick, Omit, Reduce and Partial. At the end of the video I’ll provide a bonus typescript tip that you don’t want to miss! Enjoy.


Video Version


The reason why you choose to work with typescript is its huge value added to the vanilla javascript language, writing less error prone code and identifying production bugs before they happen.

I worked with javascript for 10 years now and been using typescript for more than 5. I would never use vanilla js ever again. Typescript brings so much value to this language that it’s a no brainer to use it. If you don’t agree, let me know in the comments below and we can discuss. In the end it’s just an opinion, not a universal truth and it shouldn’t be.

Let’s set the scene and explain utility types using a proper example: User account creation & allowing profile editing

For a user to create an account we need a UI form and a server endpoint for creating the user. After the client creates his account, we allow editing the profile.

interface UserI {
  id: string;
  email: string;
  password: string;
  first_name: string;
  middle_name: string;
  last_name: string;
  date_of_birth: string;
  phone: string;
}

We share the same interface between server and frontend so that we don’t duplicate code. We already have a small problem, we can’t use this user interface for the user creation frontend nor for backend, since the form doesn’t have an id field.

Our signup form has 2 steps:

  • Step 1: email, password, confirm_password
  • Step 2: first_name, middle_name, last_name, date_of_birth, phone

Of course, we can manually define the types for both frontend and server but this means duplicated code and hard to maintain, which is a bad idea.

This is where the typescript utility types come into play and bring lots of value in

1. Pick<Type, Keys> utility type

The not recommended option: re-define manually the form types considering the user interface type.

// step 1
interface Step1Interface {
  email: string;
  password: string;
  confirm_password: string;
}

// step 2 form type
interface Step2Interface {
  first_name: string;
  middle_name: string;
  last_name: string;
  date_of_birth: string;
  phone: string;
}

We can totally do it by defining new types like in the above example. But there is a big problem – we are duplicating code (we break the DRY principle – don’t repeat yourself). In the end, the backend will validate against the user interface above.

If the user interface changes (e.g. middle_name becomes optional and phone gets removed) that cannot be reflected. Changing those will never show as error in this form and they should.

As a rule of thumb, we should never re-define a type manually from scratch if it is related / linked to another in a certain way.

This is where Pick comes into play and brings value. We can use it to create a new type based on the user interface, hence having the link between them and being warned if we do a breaking change.

Pick returns a new type by picking only a specific list of attributes from another type.

// with Pick
// returns a new type having only these attributes from the UserI

type Step1Interface = Pick<UserI, "email" | "password"> & {confirm_password: string}; 


type Step2Interface = Pick<UserI, "first_name" | "middle_name" | "last_name" | "date_of_birth" | "phone">;

/**
* Keys -> can be an attribute (e.g. "id") or a list of attributes ("id" | "first_name")
*/

Not only that this is clean, but it will also error in case we are trying to pick an attribute that doesn’t exist anymore (e.g. middle_name gets removed from UserInterface).

We can either pick one or more attributes. In case of multiple attributes we need to use the | to mention the list of attributes.

2. Omit<Type, Keys> utility type

In opposition as Pick, Omit returns a new type derived from the original interface, having all attributes except the ones we explicitly specify.

// with Omit
type Step1Interface = Omit<UserI, "id" | "first_name" | "middle_name" | "phone" | "last_name" | "date_of_birth"> & {confirm_password: string};

type Step2Interface = Pick<UserI, "id" | "email" | "password">;

/**
* Keys -> can be an attribute (e.g. "id") or a list of attributes ("id" | "first_name")
*/

3. Partial<Type> utility type

Now that the user created his account, we need our client to be able to edit his profile. We display the same form and we decide to send to the server only the changed fields.

Server side API needs a flexible enough type, not knowing in advance which fields the client edited. This is where Partial comes into play.

Using Partial returns a new type derived from User Interface which has all attributes optional.

// Partial example
type UserEditInterface = Partial<UserI>;

// equivalent of
type UserEditInterface = {
  id?: string;
  email?: string;
  password?: string;
  first_name?: string;
  middle_name?: string;
  last_name?: string;
  date_of_birth?: string;
  phone?: string;
}

4. Record<Keys, Type>

Alternatively to the Partial example above, we can use Record.

It returns a new type defining an object where you can generically specify the key type and its value type.

type UpdateProfileType = Record<string, string>

Bonus Did-You-Know Tip – How to get an interface’s attribute type

Having the following interface

interface UserI {
  id: string;
  address: {
    zip: number;
    street: {
      name: string;
      number: number;
    };
  };
}

How can we get the user’s address street type without redefining it ?

We use the object syntax on interfaces which instead of returning a value, it returns a type.

let street: UserI['address']['street'] = ...
// or
type StreetType = UserI['address']['street']

We’ll stop here for this article, I hope it was helpful and easy to follow.

Did you find this useful ? Let me know in the comment section below!

Stay tuned, video version coming soon as well.

Official Documentation

Have you also checked out our serverless framework introduction with typescript ? You can find it here.

Tags: omitpartialpickrecordtypescriptutility types
TweetShareShare
Florin Mateescu

Florin Mateescu

Programming js since 2009,I write & video about javascript and coding in general - all while building awesome projects.#buildinpublicJoin my journey!

We also recommend

React vs Angular 15 in 2023
ReactJs

ReactJs vs. Angular in 2023. A Senior Fullstack Developer perspective

December 23, 2022

Introduction In the past 2 months I started learning Angular, after 7 years of ReactJs with Typescript. As I advanced...

npm: What you are doing wrong when installing packages
Javascript

npm: What you are doing wrong when installing packages

December 19, 2022

As developers, we don't invest enough effort when we choose a javascript npm package. The simple process most developers follow...

serverless framework with typescript
DevOps

How To Add Typescript in Serverless Framework Successfully

July 25, 2022

Content: #1 What is Serverless Framework ?#2 Context#3 Configuration#4 Adding Typescript Support What is Serverless Framework Whether you use AWS,...

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

👋🏼 Hi, join me!

Twitter Youtube LinkedIn Instagram
Your Coding Hub

© 2023 binaryhub
Your Coding Blog

Content

  • Home
  • Categories
  • About
  • Contact

Follow my Journey

No Result
View All Result
  • Home
  • Categories
    • Javascript
    • Typescript
    • Serverless
    • AWS (Amazon Web Services)
    • Docker
    • Linux
    • DevOps
    • IDE
  • About
  • Contact

© 2023 binaryhub
Your Coding Blog

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In

Add New Playlist

This website uses cookies. See Cookie Policy for more information.
cropped-wp-icon.png

Welcome to your binary hub newsletter!

Get Tailored coding knowledge

🚀🚀

🚀

Get Tailored Coding Articles

Get Tailored coding knowledg

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.