我写了一些代码:
interface IEventListener {
onBefore?(name: string): void;
onAfter?(name: string): void;
}
class BaseListener implements IEventListener {
stuff() {
}
}
Run Code Online (Sandbox Code Playgroud)
这里的意图是有人可以从BaseListener他们的onBefore/ onAfter方法中获得并获得正确的类型检查:
class DerivedListener extends BaseListener {
// Should be an error (name is string, not number)
onBefore(name: number) {
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我没有收到错误DerivedListener.相反,我得到一个错误BaseListener:
类型"BaseListener"没有与"IEventListener"类型相同的属性
这是怎么回事?
implementsTypeScript中的子句完成了一件事:它确保声明类可分配给已实现的接口.换句话说,当您编写时class BaseListener implements IEventListener,TypeScript会检查此代码是否合法:
var x: BaseListener = ...;
var y: IEventListener = x; // OK?
Run Code Online (Sandbox Code Playgroud)
因此,当您编写时class BaseListener implements IEventListener,您可能打算做的是"将"可选属性"复制" IEventListener到类声明中.
相反,什么也没发生.
TypeScript 2.4改变了所有可选类型的工作方式.以前,任何没有冲突类型属性的类型都可以分配给全可选类型.这导致允许各种恶作剧:
interface HttpOptions {
method?: string;
url?: string;
host?: string;
port?: number;
}
interface Point {
x: number;
y: number;
}
const pt: Point = { x: 2, y: 4 };
const opts: HttpOptions = pt; // No error, wat?
Run Code Online (Sandbox Code Playgroud)
从2.4开始的新行为是全可选类型要求源类型至少有一个匹配属性,以使类型兼容.这会捕获上述错误并正确地指出您尝试了implements一个界面而没有实际执行任何操作.
相反,您应该使用声明合并来将接口成员"复制"到您的类中.这就像编写具有相同名称的接口声明(以及相同的类型参数,如果有的话)一样简单:
interface IEventListener {
onBefore?(name: string): void;
onAfter?(name: string): void;
}
class BaseListener {
stuff() {
}
}
interface BaseListener extends IEventListener { }
Run Code Online (Sandbox Code Playgroud)
这将导致属性IEventListener也在BaseListener,并正确标记DerivedListener原始帖子中的错误.
| 归档时间: |
|
| 查看次数: |
666 次 |
| 最近记录: |