Reputation: 397
// 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
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