Search code examples
typescripttypesinterface

Can I use a condition to define a type in an interface?


I have this interface for an item:

interface IItem {
  id: string;
  name: string;
  description: string;
  note: string | undefined;
  type: string;
  sellable: boolean;
  buyable: boolean;
  usable: boolean;
  price: number | undefined; // <--- only undefined when both buyable and sellable are false
  usage: string;
}

Because I define the items, I know that price will always be a number unless sellable and buyable is false. But as of right now, TypeScript doesn't know that. Which causes me to have to add tautologic typeguards: if (buyable) will still require another if statement: if (price), even though I know that will always be a number because of the previous if statement.

Pseudo example:

  sellable: bool
  buyable: bool
  price: if !sellable & !buyable: undefined else number

Solution

  • You can accomplish this using some additional types and type union.

    Start defining your types

    type A1 = {
      sellable: false;
      buyable: false;
      price: undefined;
    };
    
    type A2 = {
      sellable: boolean;
      buyable: true;
      price: number;
    };
    
    type A3 = {
      sellable: true;
      buyable: boolean;
      price: number;
    };
    

    Then, create a union type using all types defined above:

    type A = A1 | A2 | A3;
    

    Finally, you can define your type IItem as

    type IItem = A & {
      id: string;
      name: string;
      description: string;
      note: string | undefined;
      type: string;
      usable: boolean;
      usage: string;
    }