Call InstanceType on every value of an object type literal

161 Views Asked by At

I have an object type literal that looks like this.

class Wheels {constructor() {}}
class Frame {constructor() {}}

type Car = {
  id: number,
  wheels: typeof Wheels,
  frame: typeof Frame
}

Now I want to create a mapped type that calls InstanceType on every value of Car that is suitable.

type InstanceTypeMap<T extends object> = {
  [P in keyof T]: T[P] extends InstanceType<T[P]> ? InstanceType<T[P]> : T[P] 
}

type CarWithInstances = InstanceTypeMap<Car>

But the mapped type gives an error

Type 'T[P]' does not satisfy the constraint 'new (...args: any) => any'.
Type 'T[keyof T]' is not assignable to type 'new (...args: any) => any'.
Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'new (...args: any) => any'.
  Type 'T[string]' is not assignable to type 'new (...args: any) => any'.

So it seems that InstanceType can not guarantee that T[P] has a constructor, so how can I provide that information for the suitable values?

1

There are 1 best solutions below

0
On

I mananged to solve it right after posting the question. I just needed to change the conditional to test for if T[P] has a constructor and not if it extends its InstanceType.

type InstanceTypeMap<T extends object> = {
  [P in keyof T]: T[P] extends new (...args: any) => any ? InstanceType<T[P]> : T[P] 
}