Home > Mobile >  How to type deeply nested objects with typescript?
How to type deeply nested objects with typescript?

Time:06-28

I get product data via API, the data is deeply nested, properties might change according to the product definition. Do I need to fully type the product data in order to use typescript correctly? Or how would you approach deeply nested data in the frontend?

ts playground

const product = {
  id: 1,
  colors: ["red", "green"],
  comments: null,
  variants: [
    {
      id: 1,
      name: "t-shirt", 
      comments: null,
      material: [
        {
          id: 1,
          name: "cotton",
          comments: ["Hello World"],          
        }
      ]
    }
  ]
}

function getProduct<T>(product: T) {
  return product
}

Property 'variants' does not exist on type 'T'.

function setProductFirstVariantComment<T>(product: T, comment: string) {
  product.variants[0].comments = [comment] // TS ERROR
  return product
}

CodePudding user response:

Typescript is a type-strict language, so you need to define types to map with your data.

Without types, the compiler cannot understand which type/data you refer to. In your case, product is a generic type T but the compiler does not know what is T in your context because you never define it anywhere.

You should map your data with proper types like below

type Material = {
  id: number,
  name: string,
  comments: string[] | null,
}

type Variant = {
  id: number,
  name: string,
  comments: string[] | null,
  material: Material[]
}

type Product = {
  id: number,
  colors: string[],
  comments: string[] | null,
  variants: Variant[]
}

const productData: Product = {
  id: 1,
  colors: ["red", "green"],
  comments: null,
  variants: [
    {
      id: 1,
      name: "t-shirt", 
      comments: null,
      material: [
        {
          id: 1,
          name: "cotton",
          comments: ["Hello World"],          
        }
      ]
    }
  ]
}

function getProduct<T>(product: T) {
  return product
}

//define T which extends Product type
function setProductFirstVariantComment<T extends Product>(product: T, comment: string) {
  product.variants[0].comments = [comment]
  return product
}

setProductFirstVariantComment(productData, "new")

Playground

  • Related