2

Make the TypeScript interface partially optional/required

 2 years ago
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.
neoserver,ios ssh client

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK