Home > other >  In Typescript should I have a separate type for representing a returned record from the DB and the s
In Typescript should I have a separate type for representing a returned record from the DB and the s

Time:03-16

Struggling with a Typescript concept. In my application users can create bids or prices for products available for sale, but when doing the typing I keep going back and forth between making parameters optional so that I can pass in a partially created model to be saved and have data filled in like id, created_date, etc. and just use the same model for the return type.

It feels redundant to make multiple interfaces for what is ultimately the same model, but based on my reading I'm just thinking of this wrong and should be looking at the form data and created model separately. Just wondering if this is the accepted practice amongst people that use Typescript all the time?

interface Price {
  id?:number;
  amount: number;
  product: Product | number;
  created_on?: string; 
}

vs

interface PriceFormData {
  amount: number;
  product: number;
}

interface Price {
  id: number;
  amount: number;
  product: Product;
  created_on: string;
}

CodePudding user response:

There isn't a one-size-fits-all answer. It depends on how you use your types, and without an example of that, only hypothetical/academic advice can be given.

In a case like the one you provided, generally, it's better to define multiple, specific types which represent each possibility, and then unionize them, so that you can discriminate them when you're unsure which type you'll get. This also gives you stronger types to work with when you are sure which type you'll encounter, so won't have to perform as many checks when accessing properties, etc.

Composition of types is also powerful. Consider the following example:

TS Playground

type Product = unknown;

type Amount = { amount: number };

type PriceFormData = Amount & { product: number };

type Price = Amount & {
  created_on: string;
  id: number;
  product: Product;
};

type PriceOrFormData = Price | PriceFormData;

function findProduct (productId: number): Product {
  // ...lookup in DB
  return /* product from DB */;
}

function getProductFromPriceInfo (priceInfo: PriceOrFormData): Product {
  if ('id' in priceInfo) {
    priceInfo; // priceInfo is type Price
    return priceInfo.product;
  }
  else {
    priceInfo; // priceInfo is type PriceFormData
    return findProduct(priceInfo.product);
  }
}

Here's a another example of composition using generics.

  • Related