这应该是可能的,并且是一种有利的方法,如https://angular.io/guide/styleguide#interfaces中的状态
并在此处展示:Export class as interface in Angular2
但奇怪的是我在VSCode 1.17.2中使用Typescript 2.5.3时遇到错误
类SpecialTest中的错误
[ts] Class 'SpecialTest' incorrectly implements interface 'Test'. Types have separate declarations of a private property 'name'.
Samplecode:
class Test { private name: string; constructor(name: string) { this.name = name; } getName() { return this.name; } setName(name: string): void { this.name = name; } } class SpecialTest implements Test { private name: string; getName(): string { return ''; } setName(name: string): void { } }
我错过了什么?
编辑:
使用字符串而不是字符串,如@fenton建议的那样
解决方法
class SpecialTest extends Test {
另外,请注意字符串与字符串,因为这会让你感到震惊.你的类型注释几乎肯定是字符串(小写).
最后,您不需要手动分配构造函数参数,因此原始:
class Test { private name: string; constructor(name: string) { this.name = name; } // ... }
更好地表达为:
class Test { constructor(private name: string) { } // ... }
现在,您可以从众多问题的解决方案中进行选择.
受保护的会员
使名称成员受保护,然后您可以在子类中使用它:
class Test { protected name: string; constructor(name: string) { this.name = name; } getName() { return this.name; } setName(name: string): void { this.name = name; } } class SpecialTest extends Test { getName(): string { return ''; } setName(name: string): void { } }
接口
这是我认为最符合您需求的解决方案.
如果将公共成员拉入接口,则应该能够将这两个类视为该接口(无论是否显式使用implements关键字 – TypeScript是结构化类型).
interface SomeTest { getName(): string; setName(name: string): void; }
如果您愿意,可以明确地实现它:
class SpecialTest implements SomeTest { private name: string; getName(): string { return ''; } setName(name: string): void { } }
您的代码现在可以依赖于接口而不是具体的类.
使用类作为接口
技术上可以将类作为接口引用,但是在使用implements MyClass执行此操作之前存在问题.
首先,您为以后需要阅读代码的任何人(包括未来的代码)添加了不必要的复杂性.您还使用了一种模式,这意味着您需要注意关键字.当继承的类被更改时,意外使用extends可能会在将来导致棘手的错误.维护人员需要成为使用关键字的傻瓜.一切都是为了什么?用结构语言保留名义习惯.
接口是抽象的,不太可能改变.类更具体,更容易改变.使用类作为接口破坏了依赖于稳定抽象的整个概念……而是使您依赖于不稳定的具体类.
考虑整个程序中“类作为接口”的扩散.对类的更改(假设我们添加了一个方法)可能会无意中导致更改波动到很远的距离…程序的多少部分现在拒绝输入,因为输入不包含甚至不使用的方法?
更好的选择(当没有访问修饰符兼容性问题时)……
在类外创建一个接口:
interface MyInterface extends MyClass { }
或者,在第二堂课中根本不要引用原始课程.允许结构类型系统检查兼容性.
旁注……根据您的TSLint配置,弱类型(例如只有可选类型的接口)将触发no-empty-interface-Rule.
私人会员的具体案例
这些(使用类作为接口,从类生成接口或结构类型)都不能解决私有成员的问题.这就是为什么解决真正问题的解决方案是创建与公共成员的接口.
在私人成员的特定情况下,例如在问题中,让我们考虑如果我们继续使用原始模式会发生什么?自然结果是保留使用类作为接口的模式,成员的可见性将被更改,如下所示:
class Test { public name: string; constructor(name: string) { this.name = name; } getName() { return this.name; } setName(name: string): void { this.name = name; } }
而现在我们正在打破更为既定的面向对象原则.