Make the TypeScript interface partially optional/required
source link: https://pawelgrzybek.com/make-the-typescript-interface-partially-optional-required/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Make the TypeScript interface partially optional/required
Published: 2022.04.01 | 2 minutes read
I came across a situation when I had to make a single key of the TypeScript interface optional. Let’s say that I have a type that consists of two keys, name
and age
, and I want to make the age
key optional. My real-life scenario was more convoluted, but I just want to show you what I learned. Look!
interface Dude {
name: string;
age: number;
}
// 👍 OK, name and age are defined
const pawel: Dude = {
name: "Pawel Grzybek",
age: 34,
};
// 👎 Uuups, age is missing
const dan: Dude = {
name: "Dan Jordan",
};
TypeScript comes with two handy utility types. The Partial
converts all keys to optional and Required
that makes all keys mandatory.
interface Dude {
name: string;
age: number;
}
type DudeAllOptional = Partial<Dude>;
// 👍 OK, name and age are optional
const dan: DudeAllOptional = {};
interface Dude {
name: string;
age?: number;
}
type DudeAllRequired = Required<Dude>;
// 👎 Uuups, age is missing
const dan: DudeAllRequired = {
name: "Dan Jordan",
};
These two utility types are super helpful, but it didn’t solve my problem to make only a subset of keys optional. So I took a moment to brainstorm this idea with my friend Matias (hi dude 👋), and we came up with this solution.
interface Dude {
name: string;
age: number;
}
type DudeWithOptionalAge = Omit<Dude, "age"> & Partial<Pick<Dude, "age">>;
// 👍 name is defined, age is optional
const dan: DudeWithOptionalAge = {
name: "Dan Jordan",
};
Problem solved, but we can do better. This type looks ridiculous, and without a good coffee, I don’t want to make any edits to it. But, thanks to generics, we can wrap it in a little utility type and reuse it all over the place.
type PartiallyOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
interface Dude {
name: string;
age: number;
}
type DudeWithOptionalAge = PartiallyOptional<Dude, "age">;
// 👍 name is defined, age is optional
const dan: DudeWithOptionalAge = {
name: "Dan Jordan",
};
type PartiallyRequired<T, K extends keyof T> = Omit<T, K> &
Required<Pick<T, K>>;
interface Dude {
name: string;
age?: number;
}
type DudeWithRequiredAge = PartiallyRequired<Dude, "age">;
// 👎 Uuups, age is missing
const dan: DudeWithRequiredAge = {
name: "Dan Jordan",
};
If you know a better solution to my problem then please drop a comment below. If you don’t know a better way of doing it, I hope you learned a thing or two. Until next time, stay curious 🤩
Leave a comment
Name:
Website (optional):
Twitter (optional):
GitHub (optional):
Comment:
👆 you can use Markdown here
Save my data for the next time I comment
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK