派生类是否在 Typescript 中实现了基类的接口

派生类是否实现基类的接口?

例子:

interface IBase {
    controls : { [key: string] : number }
}

class BaseClass implements IBase {
    controls = {};
}

class TestClass extends BaseClass {
    controls = {test:'a'};
}

当接口声明它应该是一个数字时,当将控件值设置为派生类中的字符串时,上面不会抱怨。

如果我在派生类中将控件设置为 null,它会抱怨:

类型“null”不可分配给类型“{}”

在每个派生类和类中实现接口的正确方法是什么?

杰卡兹

当一个类implements成为一个接口时,它实际上并不影响类的类型。编译器检查类是否与接口兼容,但它不使用接口作为上下文来为类的成员提供类型。如果您编写class Foo implements Bar {...}并且没有编译器错误,那么编译器将对其进行处理,就好像您遗漏了implements Bar而只是编写了class Foo {...}. 有关更多信息,请参阅microsoft/TypeScript#32082和其中链接的问题。

SoBaseClasscontrols属性被推断为具有空对象类型{}您可能期望BaseClasscontrols属性为 type { [key: string] : number },但这不会发生,因为此类信息仅来自implements IBase子句,在为BaseClass的成员提供类型时会忽略子句如果你想看到一个实现类或子类具有特定类型的属性,你应该注释它们:

class BaseClass implements IBase {
    controls: { [key: string]: number } = {}; // annotated
}

class TestClass extends BaseClass {
    // you might also want to annotate this, depending on intent
    controls = { test: 'a' }; // error!
}

同样重要的是要注意,无论好坏,TypeScript 的类型系统都不是完全健全的有一些“漏洞”,TypeScript 允许不一致的赋值

在一个健全的类型系统中,子类型应该是可传递的这意味着,对于任何类型A, B, and C, if A extends Band B extends C, then A extends C虽然这在 TypeScript 中很常见,但有时会被违反。这就是您的示例中发生的情况:TestClass extends BaseClass, 和BaseClass extends IBase,但TestClass不扩展IBase

如果我们创建一个VerifyExtends<T, U>只编译 if的辅助类型函数T extends U,我们就可以亲眼目睹子类型化的这种不传递性:

type VerifyExtends<T extends U, U> = void;    
type AB = VerifyExtends<TestClass, BaseClass> // okay
type BC = VerifyExtends<BaseClass, IBase> // okay
type AC = VerifyExtends<TestClass, IBase> // error!

TestClass extends BaseClass因为controlsin属性TestClass有一个BaseClass( {})中没有提到的额外属性,可以通过添加属性来扩展对象类型。

并且BaseClass extends TestClass因为它的controls属性{}具有与索引签名冲突的属性(它根本没有属性)......并且 TypeScript 将为这些类型提供隐式索引签名

但是当然TestClass不会扩展,IBase因为额外的属性和隐式索引签名是不相互一致的。所以我们有奇怪的地方。


在你的情况下,我可能会建议明确的注释,因为这是你的意图。但是您迟早会遇到不健全的情况,您应该为此做好准备。

Playground 链接到代码

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

TypeScript:检查派生类是否实现方法

来自分类Dev

Typescript typeof类和派生类

来自分类Dev

派生类的Typescript方法修饰器

来自分类Dev

TypeScript注释派生类的继承成员

来自分类Dev

在基类中定义接口后,是否需要在派生类中定义相同的接口?

来自分类Dev

明确标记派生类为基类的实现接口

来自分类Dev

找出类在TypeScript中实现了哪些接口

来自分类Dev

如何避免在TypeScript,Angular2的派生类中重复基类构造函数参数?

来自分类Dev

派生类中的Typescript推断函数参数

来自分类Dev

在基类中声明的C#接口方法无需在派生类中再次实现

来自分类Dev

从基类的派生类(从接口)中调用函数

来自分类Dev

扩展传递给派生类的选项的Typescript最佳实践

来自分类Dev

TypeScript 装饰器不适用于派生类

来自分类Dev

从派生类中隐藏基类的实现细节

来自分类Dev

强制派生类实现接口

来自分类Dev

指向派生类的指针是否首先创建基类?

来自分类Dev

派生类是否被视为基类的成员?

来自分类Dev

Typescript:类实现接口问题?

来自分类Dev

当基类实现抽象时,在派生类上指定实现接口

来自分类Dev

Typescript:(中间值)。(...)从派生类中调用父类的方法时不是函数

来自分类Dev

为具有TypeScript中类型变量的抽象类的派生类分配通用类型

来自分类Dev

是否可以在派生类中实现抽象方法,但只能在基类中调用抽象方法?

来自分类Dev

TypeScript推断接口实现类中的类型参数

来自分类Dev

枚举在Typescript中实现接口的所有类

来自分类Dev

C#:我的派生类无法覆盖基类的接口方法实现,为什么?

来自分类Dev

基类实现接口

来自分类Dev

是否可以在接口的派生类中仅使用C#中的该接口的某些方法?

来自分类Java

是否可以在派生类中重写静态方法?

来自分类Dev

派生类模板

Related 相关文章

  1. 1

    TypeScript:检查派生类是否实现方法

  2. 2

    Typescript typeof类和派生类

  3. 3

    派生类的Typescript方法修饰器

  4. 4

    TypeScript注释派生类的继承成员

  5. 5

    在基类中定义接口后,是否需要在派生类中定义相同的接口?

  6. 6

    明确标记派生类为基类的实现接口

  7. 7

    找出类在TypeScript中实现了哪些接口

  8. 8

    如何避免在TypeScript,Angular2的派生类中重复基类构造函数参数?

  9. 9

    派生类中的Typescript推断函数参数

  10. 10

    在基类中声明的C#接口方法无需在派生类中再次实现

  11. 11

    从基类的派生类(从接口)中调用函数

  12. 12

    扩展传递给派生类的选项的Typescript最佳实践

  13. 13

    TypeScript 装饰器不适用于派生类

  14. 14

    从派生类中隐藏基类的实现细节

  15. 15

    强制派生类实现接口

  16. 16

    指向派生类的指针是否首先创建基类?

  17. 17

    派生类是否被视为基类的成员?

  18. 18

    Typescript:类实现接口问题?

  19. 19

    当基类实现抽象时,在派生类上指定实现接口

  20. 20

    Typescript:(中间值)。(...)从派生类中调用父类的方法时不是函数

  21. 21

    为具有TypeScript中类型变量的抽象类的派生类分配通用类型

  22. 22

    是否可以在派生类中实现抽象方法,但只能在基类中调用抽象方法?

  23. 23

    TypeScript推断接口实现类中的类型参数

  24. 24

    枚举在Typescript中实现接口的所有类

  25. 25

    C#:我的派生类无法覆盖基类的接口方法实现,为什么?

  26. 26

    基类实现接口

  27. 27

    是否可以在接口的派生类中仅使用C#中的该接口的某些方法?

  28. 28

    是否可以在派生类中重写静态方法?

  29. 29

    派生类模板

热门标签

归档