0

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
}
1
  • 1
    You need to use appropriate constraint. See here . However, may I ask, why do you return product and in the same time mutate it. As per my understanding, if you want to retyrn new product, you should return new reference or, if you mutate product, you should not return anything Commented Jun 28, 2022 at 7:54

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.