Home > OS >  TS2322: Type '(new () => typeof Rectangle)[]' is not assignable to type 'Rectangle
TS2322: Type '(new () => typeof Rectangle)[]' is not assignable to type 'Rectangle

Time:02-18

I have a function that stamps copies of classes. It takes a class and returns as many copies of classes as I specified. But the problem is not in the function but in its signature. To create new classes I need a function new and to connect it I did extends { new(): T }. I need it to return an array of classes with their type, but instead it returns (new () => typeof Rectangle)[] and I can't figure out what the problem is. Here is the code.

class Rectangle {
    w!: number;
    h!: number;
}
class Circle {
    radius!: number;
}


function stampFigures<T extends { new (): T } >(someClass: T, count: number): T[] {
    let a = []
    for (let i = 0; i < count; i  )
        a.push(new someClass());

    return a;
}

let a: Rectangle[] = stampFigures(Rectangle, 10); //here i need Rectangle[] but i got (new () => typeof Rectangle)[]
let b: Circle[] = stampFigures(Circle, 20) //and here

console.log(a)
console.log(b)

CodePudding user response:

You need to infer an instance type of class:

class Rectangle {
  w!: number;
  h!: number;
}
class Circle {
  radius!: number;
}


function stampFigures<
  Klass extends { new(): any }
>(someClass: Klass, count: number) {
  let a: InstanceType<Klass>[] = []
  for (let i = 0; i < count; i  )
    a.push(new someClass());

  return a;
}

let a = stampFigures(Rectangle, 10); //  Rectangle[]
let b = stampFigures(Circle, 20) // Circle[]

console.log(a)
console.log(b)

Playground

YOu can also check my article

If you are interested in safest solution, you can create base class and extends your classes with tag property. In other words, discriminate it.

class Shape {
  tag: string = ''
}

class Rectangle extends Shape {
  tag = 'Rectangle'
  w!: number;
  h!: number;
}

class Circle extends Shape {
  tag = 'Circle'

  radius!: number;
}


function stampFigures<
  Klass extends typeof Shape,
  Instance extends InstanceType<Klass>
>(someClass: Klass & (new () => Instance), count: number) {
  let a = []
  for (let i = 0; i < count; i  )
    a.push(new someClass());

  return a;
}

let a = stampFigures(Rectangle, 10); //  Rectangle[]
let b = stampFigures(Circle, 20) // Circle[]

console.log(a)
console.log(b)

Playground

  • Related