TypeScript | What is the Partial Type and How to use it?

TypeScript is easy to learn for those with a JavaScript background. However, the more you use it, the more you hear about types you have never heard of, especially utility types such as the omit type or the partial type, which we will explain in this article.

The partial utility type was introduced in TypeScript release 2.1 and it is designed to make all of the properties of a type optional. This means developers will no longer have to provide values to all properties of a type. In fact, it opens the possibility of not providing any property.

How to use the Partial<T> type

The partial type is simple to use as it only requires to pass a type T where T can be any object type regardless of whether it is a defined type.

Partial<MyType>
Partial<MyInterface>
Partial<{}>

To better understand the partial type, let’s take a look at the following example where we have the Blog interface.

interface Blog {
  id: string;
  title: string;
  slug: string;
  categories: string[];
  tags: string[];
  featureImageUrl?: string;
  content: string;
}

Notice the Blog interface is composed of six property keys, which all except by featureImageUrl are required. Therefore, in case we want to assign a value to a variable with the type of Blog, we will have to fill in all the necessary data to make up for an object that follows the Blog interface.

const latestBlog: Blog = {
   id: '1',
   title: 'TypeScript | What is the Partial Type and How to use it?',
   slug: 'typescript-partial-type',
   categories: ['typescript'],
   tags: [],
   featureImageUrl: 'path/of/feature/image',
   content: 'TypeScript is easy to learn for those with a JavaScript background. However, the more you use it, the more you hear about types you have never heard of, especially utility types such as the omit type or the partial type, which we will explain in this article.'
};

However, it is common during the development to not know all the values of a Blog, especially when we have a draft of a blog. However, failing to pass all the property keys will lead to a TypeScript error. For instance, if we only pass the title property in a draft variable like in the snippet of code below

const draft: Blog = {
  title: 'What kind of title should I type?'
}

TypeScript will show the following error at the moment of transpiling the TypeScript code into JavaScript.

Type '{ title: string; }' is missing the following properties from type 'Blog': slug, categories, tags, content ts(2739)

Or if you are using an IDE like VS Code, it will show you the error even before the code is saved.

Typescript error when missing required property keys

An alternative solution is to make all of the properties optional using the question mark ?.

interface Blog {
  id?: string; 
  title?: string;
  slug?: string;
  categories?: string[];
  tags?: string[];
  featureImageUrl?: string;
  content?: string;
}

const draft: Blog = {
  title: 'What kind of title should I type?'
}

However, it is not always possible to make all of the property keys optional. Besides, it will prevent from enforcing property values in certain types. That’s when the partial type becomes useful as it makes all these properties optional without the need of modifying the requirement of the properties of the type like in the following example.

// no need to update all the property keys to be optional
interface Blog {
  id: string;
  title: string;
  slug: string;
  categories: string[];
  tags: string[];
  featureImageUrl?: string;
  content: string;
}

// Partial<Blog> generates a new type based on Blog with all the property
// keys being optional
const draft: Partial<Blog> = {
  title: 'What kind of title should I type?'
}

Understanding the Partial<T> Type Definition

If you have TypeScript installed in your machine, the Partial utility type definition can be found in the file typescript/lib/lib.es5.d.ts. Also, the TypeScript repository is publicly accessible you can access the definition of Partial.

/**
 * Make all properties in T optional
 */
 type Partial<T> = {
  [A in keyof T]?: T[A];
};

However, what does this mean?

As always, I recommend breaking it down into smaller chunks to make it simpler to understand.

type Partial<T> = { [A in keyof T]?: T[A] }; // what is this?
[A in keyof T]?: T[A]                        // what is this?
[A in keyof T]?                              // what is this?
keyof T                                      // what is this?

The only part we know is T, which is the type passed to work with Partial, which could be the Blog interface we used in the previous examples.

Given keyof T , which is keyof Blog if we use the Blog type, we have:

type BlogKeys = keyof Blog;

// it is the equivalent of
type BlogKeys = 'title' | 'slug' | 'categories' | 'tags' | 'featureImageUrl' | 'content';

Then, we know that [A in keyof T]? is:

[A in 'title' | 'slug' | 'categories' | 'tags' | 'featureImageUrl' | 'content']?

Hence, A must be any of the property keys of the Blog type.

['title']? = Blog['title']                      // or title? = Blog['title']
['slug']? = Blog['slug']                        // or slug? = Blog['slug']
['categories']? = Blog['categories']            // or categories? = Blog['categories']
['tags']? = Blog['tags']                        // or tags? = Blog['tags']
['featureImageUrl']? = Blog['featureImageUrl']  // or featureImageUrl? = Blog['featureImageUrl']
['content']? = Blog['content']                  // or content? = Blog['content']

And all of the properties have the question mark (?) to denote the property key is optional. Therefore, it is like having this OtherBlog interface with all optional keys.

interface OtherBlog {
  title?: string;
  slug?: string;
  categories?: string[];
  tags?: string[];
  featureImageUrl?: string;
  content?: string;
}

Useful Cases to use the Partial<T> type

When updating only some fields of an object

Think about when an object, in our examples, a Blog, is updated. Do all of the properties of the Blog update at the same time? Probably not. Hence, the updateBlog function below would make for a great candidate to use the partial type for the blog parameter.

async function updateBlog(id: string, blog: Partial<Blog>) {
   await db.Blog.save(id, {
   ...blog
   });
}

When passing constructor values to populate an new instance of a class

If you happen to define classes in TypeScript and like to use the constructor to populate the initial property values of a class, the partial type is an excellent choice. The reason is, JavaScript doesn’t support multiple constructors like other programming languages such as C#.

interface IBlog {
  title: string;
  slug: string;
  categories: string[];
  tags: string[];
  featureImageUrl?: string;
  content: string;
}


class Blog implements IBlog {
  title!: string;
  slug!: string;
  categories!: string[];
  tags!: string[];
  featureImageUrl?: string;
  content!: string;

  // class cann ONLY accept one constructor
  constructor(title: string) {
    this.title = title;
  }
  
 // cannot have another constructor
  constructor(title: string, categories: string[]) {
    this.title = title;
    this.categories = categories
  }

  // cannot have another constructor
  constructor(title: string, slug: string) {
    this.title = title;

    this.slug = slug;
  }
}

Therefore, it would be challenging to create an instance of a class as based on different scenarios, you might not pass any argument to a constructor, or pass the title, or pass a combination of title and slug, etc.

Using the partial type solves this issue as it gives us the flexibility we need to pass initial values in the constructor of a class due to the restriction of only defining one constructor in JavaScript.

class Blog implements IBlog {
  title!: string;
  slug!: string;
  categories!: string[];
  tags!: string[];
  featureImageUrl?: string;
  content!: string;

  constructor(data: Partial<IBlog>) {
    Object.assign(this, data);
  }
}

Make a property required and the rest optional (BONUS)

There are special scenarios where we would want to keep certain properties required, but let the rest be optional. For example, assume we must update the title of a Blog type every time we trigger the updateBlog function.

Unfortunately, using the Partial type with not work as you know by now, it will make all the properties optional.

async function updateBlog(id: string, blog: Partial<Blog>) {
   await db.Blog.save(id, {
   ...blog
   });
}

However, we can use Partial in combination with Pick utility type to enforce the property title. to be passed as part of the blog parameter.

async function updateBlog(id: string, blog: Partial<Blog> & Pick<Blog, 'title'>) {
  await db.Blog.save(id, {
    ...blog
  });
}

Other TypeScript articles you might be interested in reading

There is a list of TypeScript articles you might be interested in checking out:

If none of them are of your interest, feel free to check out the blog to check for more TypeScript and other web development-related articles.

Conclusion

All in all, Partial is a nifty utility type that allows us to have flexibility out of the types defined in the code without the need to make all property keys optional to create objects where not all the property data is available. The partial type becomes useful to make all of these property keys optional without having to define a completely new type.

Did you like this article?

Share your thoughts by replying on Twitter of Become A Better Programmer or to personal my Twitter account.