I start saying that StackOverflow has plenty of questions about this error message, but none of them helped me, they are just different cases.
I'm trying to build a function that accepts a union type A|B and returns, accordingly, A or B.
An example is this playground:
class Cat {
meow() {}
clone(): Cat {
return new Cat;
}
}
class Dog {
woof() {}
clone(): Dog {
return new Dog;
}
}
type Animal = Cat | Dog;
function clone<T extends Animal>(animal: T): T {
if (animal instanceof Cat) {
animal.meow();
} else if (animal instanceof Dog) {
animal.woof();
}
return animal.clone();
}
But I receive the following error:
Type 'Animal' is not assignable to type 'T'. 'Animal' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Animal'. Type 'Cat' is not assignable to type 'T'. 'Cat' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Animal'.
I expect to use it like:
const dog = new Dog();
const otherDog = clone(dog);
// otherDog's type is Dog and not Animal
I think the use of the keyword extends
is wrong here, because I'm not supposed to extend a union type, but use one of the parts of the union type. But writing:
function clone(animal: Animal): Animal {
then the returned type is always Animal
, and not Dog
or Cat
. I don't want explicitly assert the type.
How can I solve the problem? Thank you