typescript - 为什么实现接口(interface)的类中的泛型成员函数不能采用类(而不是接口(interface))类型的参数?

标签 typescript typescript-types

考虑一个接口(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/

相关文章:

javascript - 从 typescript 编译后,此关键字在浏览器中给出空引用错误

javascript - Angular 5/6 : Handle File Download (w/Friendly File Name) from ASP. NET 核心 API HTTP

AngularJs + typescript : error TS2307: Cannot find module 'angular'

typescript - 采取受歧视工会的补充

c# - 仅使用 POCO 的项目上的 TypeLite?

typescript :映射类型:没有方法的类到接口(interface)

typescript - 扩展@types - 从接口(interface)中删除字段,将类型添加到接口(interface)中的字段

typescript - 从接口(interface)属性创建联合类型

reactjs - 如何使用 TypeScript 以类型安全的方式访问 React 子元素 Prop ?

angularjs - AngularJS $routeProvider 模块的 TypeScript 示例