1

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

  • Does this answer your question? [could be instantiated with a different subtype of constraint 'object'](https://stackoverflow.com/questions/56505560/could-be-instantiated-with-a-different-subtype-of-constraint-object) – bugs Sep 02 '20 at 13:17
  • adding `return animal.clone() as T;` fixes the issue :) – Ric Sep 02 '20 at 13:25
  • @Ric thank you, it worked. Add it as an answer and I'll accept it – Christian Vincenzo Traina Sep 02 '20 at 14:54

0 Answers0