考虑一个接口(interface) IDog
与方法 likes<T extends IDog>( other: T )
.该方法采用一个类型扩展接口(interface)的参数。为什么不允许在派生类中实现该方法 Dog
使用类作为参数的类型而不是接口(interface)?
interface IDog
{
likes<T extends IDog>( other: T ): boolean;
}
class Dog implements IDog
{
private name = "Buddy";
public likes<T extends Dog>( other: T )
// ^^^^^
// error: Property 'likes' in type 'Dog' is not
// assignable to the same property in base type 'IDog' [...]
// Property 'name' is missing in type 'IDog' but required in type 'Dog'
{
return true;
}
}
移除私有(private)属性(property) name
会使错误消失,但不是我现实世界问题的解决方案。奇怪的是,没有泛型的同一个例子工作得很好:interface ICat
{
likes( other: ICat ): boolean;
}
class Cat implements ICat
{
private name = "Simba";
public likes( other: Cat ) // no error using Cat here (instead of ICat)
{
return true;
}
}
我在这里缺少什么?
最佳答案
想象这样一种情况:你有
const myDog: Dog
const someOtherDog: IDog
和这样的功能:function seeIfLikes(dog: IDog, anotherDog: IDog) {
return dog.likes(anotherDog)
}
这个功能好像还行,IDog.likes()
想要扩展的东西 IDog
作为论据。但是当你拨打
seeIfLikes(myDog, someOtherDog)
,出乎意料的事情发生了:myDog
被转换为 IDog
,所以 TypeScript 会忘记它的 likes()
方法需要扩展 Dog
的东西,不是 IDog
!所以即使
someOtherDog
这个函数调用也会通过类型检查实际上并没有扩展 Dog
- 如果您的 Dog.likes()
包含一些特定于 Dog
的代码类,不至 IDog
,你会得到一个运行时kaboom。这就是我们不能在子类型中添加新的泛型参数限制的原因:它们可能会被强制转换为它们的父类(super class)型,并且该限制将消失。希望这足够清楚理解。
是的,那个
Cat
示例将遇到完全相同的问题,但 tsc 让它以未知原因通过。也许这是类型系统的限制,或者更好地报告的错误。
关于typescript - 为什么实现接口(interface)的类中的泛型成员函数不能采用类(而不是接口(interface))类型的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68681526/