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.
Table of Contents
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.
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:
- TypeScript | Learn How to Pass a Function as a Parameter
- TypeScript | The Guide You Need to Learn the Omit Type
- Understanding the Question Mark (?:) in TypeScript
- TypeScript | The Unknown Type Guide
- TypeScript | Organizing and Storing Types and Interfaces
- TypeScript | Double Question Marks (??) – What it Means
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.