spb
spb

Reputation: 987

Make some properties optional in a TypeScript type

If I have a type with all required properties, how can I define another type with the same properties where some of it's properties are still required but the rest are optional?

For example I want a new type derived from SomeType where prop1 and prop2 are required but the rest are optional:

interface SomeType {
    prop1;
    prop2;
    prop3;
    ...
    propn;
}

interface NewType {
    prop1;
    prop2;
    prop3?;
    ...
    propn?;
}

Upvotes: 33

Views: 32796

Answers (5)

Andy
Andy

Reputation: 2364

Here is another way

export type ContactInfoFormInput = Pick<AccountDetails, 'email' | 'phone'> &
  Pick<Profile, 'firstName' | 'lastName'> & {
    dateCreated?: Profile['dateCreated'];
  };

So in this example, email, phone, firstName, lastName are all required but dateCreated which also comes from the Profile base type is optional

Upvotes: 0

Noy Oliel
Noy Oliel

Reputation: 1696

From this article:

We can derive the following type:

export type PartialPick<T, F extends keyof T> = Omit<T, F> & Partial<Pick<T, F>>;

F - the fields that should be made optional

T - the type

In your example:

type NewType = PartialPick<SomeType, 'prop3' | ... | 'propn'>

If you'd like to make some properties required instead of the partial use:

type RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>;

If NewType should be an interface and has additional fields besides the fields in SomeType, you can use extends from the type:

interface SomeType {
    prop1;
    prop2;
    prop3;
    prop4;
}
interface NewType extends PartialPick<SomeType, 'prop3' | 'prop4'> {
    prop5;
}

Upvotes: 4

M Fuat
M Fuat

Reputation: 1440

type onlyOneRequired = Partial<Tag> & {id: string}

In the above type, all properties of Tag are optional instead of id which is required. So you can use this method and specify the required properties.

Upvotes: 6

For tetter performance, in addition to Titian's answer, you must do :

type OptionalExceptFor<T, TRequired extends keyof T = keyof T> = Partial<
  Pick<T, Exclude<keyof T, TRequired>>
> &
  Required<Pick<T, TRequired>>;

Upvotes: 5

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 250306

You can use combination of Partial and Pick to make all properties partial and then pick only some that are required:

interface SomeType {
    prop1: string;
    prop2: string;
    prop3: string;
    propn: string;
}

type OptionalExceptFor<T, TRequired extends keyof T> = Partial<T> & Pick<T, TRequired>

type NewType = OptionalExceptFor<SomeType, 'prop1' | 'prop2'>

let o : NewType = {
    prop1: "",
    prop2: ""
}

Upvotes: 69

Related Questions