[SOLVED] Typescript Generics for nested array of objects

Issue

Hello i am trying to add correct type to object with nested values.

Here is code in sandbox:
https://codesandbox.io/s/0tftsf

interface Product {
  name: string,
  id: number
  productList?:ProductItem[]
}

interface ProductItem { 
  color: string, 
  size: number 
 }


type IValidation<T> = {
  field: keyof T
  nestedValidations?: IValidation<
    Pick<
      T,
      {
        [K in keyof T]-?: T[K] extends object ? K : never
      }[keyof T]
      >
    >[] // THIS IS IMPORTANT FOR QUESTION!
  validators?: (any | any | any)[]
}

export async function validateIt<T>(payload: T, validations: IValidation<T>[]): Promise<
  Partial<{
    [key in keyof T]: string[]
  }>
  > { 
    return Promise.resolve(payload);
  }

const product: Product = {
  id: 1,
  name: 'playstation',
  productList: [{
    color: 'red',
    size: 32
    }
  ]
}

const test = validateIt<Product>(product, [
  {
    field: "productList",
    validators: [],
    nestedValidations: [
      {
        field: 'color',
        validators: []
      }
    ]
  }
])

So getting type error and overall i am trying to find correct type for nestedValidations property, which should match interface Product

ERROR

Solution

You can achieve this with in keyword in combination with keyof.
Basically you’re going to "generate" all possible types for each key and typescript will find matching one

type IValidation<T> = T extends Array<infer R> ? IValidation<R> : T extends object ? {
    [K in keyof T]: {
        field: K
        nestedValidations?: IValidation<T[K]>[]
        validators?: (any | any | any)[]
    }
}[keyof T] : never

Playground link

Answered By – BorisTB

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *