Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make all properties within a Typescript interface optional

Tags:

typescript

People also ask

How do I make all properties in a TypeScript interface optional?

Use the Partial utility type to make all of the properties in a type optional, e.g. const emp: Partial<Employee> = {}; . The Partial utility type constructs a new type with all properties of the provided type set to optional. Copied!

How do I make my properties optional TypeScript?

To make a single property in a type optional, create a utility type that takes a type and the property name as parameters and constructs a new type with the specific property marked as optional. Copied!

How do you override properties in interface TypeScript?

Use the Omit utility type to override the type of an interface property, e.g. interface SpecificLocation extends Omit<Location, 'address'> {address: newType} . The Omit utility type constructs a new type by removing the specified keys from the existing type.

Can we have an interface with optional and default properties in TypeScript?

If you want to set the properties of an interface to have a default value of undefined , you can simply make the properties optional. Copied!


This isn't possible in TypeScript < 2.1 without creating an additional interface with optional properties; however, this is possible by using mapped types in TypeScript 2.1+.

To do this, use the Partial<T> type which TypeScript provides by default.

interface PostDraft {
    asset: Partial<Asset>;
}

Now all the properties on asset are optional, which will allow you to do the following:

const postDraft: PostDraft = {
    asset: {
        id: "some-id"
    }
};

About Partial<T>

Partial<T> is defined as a mapped type that makes every property in the provided type optional (using the ? token).

type Partial<T> = {
    [P in keyof T]?: T[P];
};

Read more about mapped types here and in the handbook.

Deep Partial

If you want a partial implementation that works recursively on objects then you can use the following type in TS 4.1+:

type DeepPartial<T> = {
    [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

The properties in the interface are either optional are not, you can not use the same interface once as optional and once as must.

What you can do is to have an interface with optional properties for the AssetDraft and then a class with mandatory properties for the Asset:

interface AssetDraft {
    id?: string;
    internal_id?: string;
    usage?: number;
}

class Asset {
    static DEFAULT_ID = "id";
    static DEFAULT_INTERNAL_ID = "internalid";
    static DEFAULT_USAGE = 0;

    id: string;
    internal_id: string;
    usage: number;

    constructor(draft: AssetDraft) {
        this.id = draft.id || Asset.DEFAULT_ID;
        this.internal_id = draft.internal_id || Asset.DEFAULT_INTERNAL_ID;
        this.usage = draft.usage || Asset.DEFAULT_USAGE;
    }
}

The default values here are static members, but you can get those in other ways or throw an error in case they are missing.

I find this way very comfortable when working with jsons that are received from the server (or something similar), the interfaces represent the json data and the classes are the actual models that are constructed using the jsons as initial values.


If I want to have an explicit AssetDraft interface, I would use a combination of extends and Partial:

interface Asset {
  id: string;
  internal_id: string;
  usage: number;
}

interface AssetDraft extends Partial<Asset> {}