crazyones110
crazyones110

Reputation: 397

Type inference with generic array in Typescript

// Generic Constraints
class Car {
  print() {
    console.log('I am a car')
  }
}
class House {
  print() {
    console.log('I am a house')
  }
}

interface Printable {
  print(): void;
}

// tell Typescript that I promise the T type will satisfy the Printable interface
function printHousesOrCars<T extends Printable>(...arr: T[]): void {
  arr.forEach(item => item.print())
}

printHousesOrCars(1, 2, 3) // This line went wrong,I can understand
printHousesOrCars(new House(), new Car()) // this line Typescript infer T[] is Car[], I cannot understand, why shouldn't it be (House|Car)[]

I cannot understand the last line, and if I wrote

const x = [new House(), new Car()] // Typescript will infer x as (House|Car)[]

Upvotes: 0

Views: 720

Answers (1)

rusev
rusev

Reputation: 1920

The following line will be interpreted by the Typescript as a two elements tuple of type [House, Car].

const x = [new House(), new Car()] // Typescript will infer x as (House|Car)[]

It's a bit confusing, I know, because of both using the same syntax i.e the [ and ].

Now you can modify the function signature a bit in order to produce, what I believe, more correct typing.

function printHousesOrCars<T extends Printable[]>(...arr: T): void {
  arr.forEach(item => item.print())
}

On the call site the above will be resolved as a function with first arg House and a second Car.

printHousesOrCars(new House(), new Car()) // [House, Car]

Playground More on the rest parameters subject

I hope this makes sense. :)

Upvotes: 3

Related Questions