1

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

1
  • updated with an idea Commented Mar 23, 2022 at 8:34

2 Answers 2

2
+50

Typescript v3.7 and later

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


This doesn't work in older typescript versions, because they don't allow recursive types. Link to info.
Sign up to request clarification or add additional context in comments.

5 Comments

Perfect sir own you a beer please vote up! Tnx once again!
I think this is not right since gettng Type alias 'IValidation' circularly references itself error
Thanks, I've added info that this only works with TS versions that support recursive types (3.7+)
tnx, but is there some workaround for older types?
0

Maybe I don't see the big picture but I think you want to achieve this:

interface Product {
  name: string,
  id: number
}

type ValueOf<T> = T[keyof T]; // not needed

type IValidation<T> = {
  field: keyof T
  nestedValidations?: IValidation<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'
}

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

Play around here: Typescript Playground

Please note that I had to simplify your data structure since I don't know how 'IRequiredValidator' is defined.

So basically we switch from

nestedValidations?: IValidation<ValueOf<T>>[]

to

nestedValidations?: IValidation<T>[]

because you want to extract the keys of T and not the keys of ( keys of T) Since that would resolve to all the properties of the type of a value assigned to a property of T.

5 Comments

No IValidation<T>[] will use just a storeProductImageList key, i need here this part StoreProductImage from export type PostStoreProductPayload = { storeProductImageList?: StoreProductImage[] }
updated with an idea it is close but no cigar
here it is code in sandbox codesandbox.io/s/0tftsf
I was playing around with your example and came up with type IValidation<T, P extends keyof T> = { field: P, validators?: ..., nestedValidations?: IValidation<T[P], keyof T[P]>[]; } However, there's an issue with trying to define types and validation for types like this: what is a key of a ProductItem[]? 0, 1, 2, ... You should try reapproaching the design with the visitor pattern.
do you have some examples?

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.