Search code examples
typescript

Make all properties within a Typescript interface optional


I have an interface in my application:

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

that is part of a post interface:

interface Post {
  asset: Asset;
}

I also have an interface that is for a post draft, where the asset object might only be partially constructed

interface PostDraft {
  asset: Asset;
}

I want to allow a PostDraft object to have a partial asset object while still checking types on the properties that are there (so I don't want to just swap it out with any).

I basically want a way to be able to generate the following:

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

without entirely re-defining the Asset interface. Is there a way to do this? If not, what would the smart way to arrange my types in this situation be?


Solution

  • 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];
    };