Search code examples
typescriptdiscriminated-uniontypescript-utility

Typescript - Create a subset of discriminated union as a discriminated union


Is there a way to create a subset discriminated union by picking some fields from another discriminated union?

For example:

type Listing = {
  type: 'rent';
  title: string;
  userId: string;

  dailyPrice: number;
  monthlyPrice: number;
  
} | {
  type: 'sell',
  title: string;
  userId: string;
  
  sellPrice: number;
}

into

type ListingBrief {
  type: 'rent';
  dailyPrice: number;
  monthlyPrice: number;
} | {
  type: 'sell';
  sellPrice: number;
}

So what I want is something like Pick<Listing, 'type' | 'dailyPrice' | 'monthlyPrice' | 'salePrice'>. But seems Typescript doesn't allow picking fields that only exist in one type i.e dailyPrice, monthlyPrice, and salePrice. Fields like title, userId can be picked because they exist in all of the types.


Solution

  • Typescript doesn't allow picking fields that only exist in one type

    You can just write your own MyPick utility type.

    type MyPick<T, K extends T extends infer R ? keyof R : never> = 
        T extends infer R 
        ? { [P in K as P extends keyof R ? P : never]: R[P]; } 
        : never
    ;
    
    type Result = MyPick<Listing, 'type' | 'dailyPrice' | 'monthlyPrice' | 'sellPrice'>;