Reputation: 874
I want to create a one-argument method where the rhs can only be of the exact same type as the lhs – not any of its superclasses or subclasses. What's the right type to use?
The following code illustrates what I want to achieve. For the purpose of this question, I used self
but I suspect that it means something else.
abstract class Animal {
public mateWith(animal: self): void {
// ... HERE ⤴️
}
}
class Dog extends Animal {}
class Cat extends Animal {}
class Tiger extends Cat {}
const dog1 = new Dog();
const dog2 = new Dog();
const cat = new Cat();
const tiger = new Tiger();
dog1.mateWith(dog2); // Valid
dog1.mateWith(cat); // Invalid
cat.mateWith(tiger); // Also invalid
Upvotes: 2
Views: 58
Reputation: 66718
Instead of self
you want this
for the actual abstract class name.
I don't know if it's possible to dynamically check for the subclass and I suspect you'll want to have it be invalid on compile-time.
Yet as a workaround you'll could make do with a run-time check via the help of the constructor name:
abstract class Animal {
public mateWith(animal: this): string {
const msg = `${animal.constructor} with: ${this.constructor}, that: `;
if (animal.constructor !== this.constructor) {
return msg + "WON'T work!".trim() + "\n";
}
return msg + "works!".trim() + "\n";
}
}
class Dog extends Animal {
}
class Cat extends Animal {
}
class Tiger extends Cat {
}
const dog1 = new Dog();
const dog2 = new Dog();
const cat = new Cat();
const tiger = new Tiger();
console.log(
dog1.mateWith(dog2),
dog1.mateWith(cat),
cat.mateWith(tiger),
);
It will output:
class Dog extends Animal {
} with: class Dog extends Animal {
}, that: works!
class Cat extends Animal {
} with: class Dog extends Animal {
}, that: WON'T work!
class Tiger extends Cat {
} with: class Cat extends Animal {
}, that: WON'T work!
Upvotes: 1