为什么TypeScript中的类允许使用duck typing
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么TypeScript中的类允许使用duck typing相关的知识,希望对你有一定的参考价值。
在TypeScript中看起来绝对没问题(从编译器的角度来看)有这样的代码:
class Vehicle {
public run(): void { console.log('Vehicle.run'); }
}
class Task {
public run(): void { console.log('Task.run'); }
}
function runTask(t: Task) {
t.run();
}
runTask(new Task());
runTask(new Vehicle());
但与此同时,我希望编译错误,因为Vehicle
和Task
没有任何共同之处。
理智的用法可以通过显式接口定义来实现:
interface Runnable {
run(): void;
}
class Vehicle implements Runnable {
public run(): void { console.log('Vehicle.run'); }
}
class Task implements Runnable {
public run(): void { console.log('Task.run'); }
}
function runRunnable(r: Runnable) {
r.run();
}
runRunnable(new Task());
runRunnable(new Vehicle());
...或共同的父对象:
class Entity {
abstract run(): void;
}
class Vehicle extends Entity {
public run(): void { console.log('Vehicle.run'); }
}
class Task extends Entity {
public run(): void { console.log('Task.run'); }
}
function runEntity(e: Entity) {
e.run();
}
runEntity(new Task());
runEntity(new Vehicle());
是的,对于javascript来说,拥有这样的行为绝对没问题,因为根本没有类,也没有编译器(只有语法糖),而鸭子打字对于语言来说是很自然的。但TypeScript试图引入静态检查,类,接口等。但在我看来,类实例的鸭子类型看起来相当混乱和容易出错。
这是结构类型的工作方式。 Typescript有一个结构类型系统,可以最好地模拟Javscript的工作方式。由于Javascript使用duck typing,因此任何定义契约的对象都可以在任何函数中使用。 Typescript只是尝试在编译时而不是在运行时验证duck typing。
但是,只有在添加私有类时,您的问题才会显示为普通类,即使它们具有相同的结构,类也会变得不兼容:
class Vehicle {
private x: string;
public run(): void { console.log('Vehicle.run'); }
}
class Task {
private x: string;
public run(): void { console.log('Task.run'); }
}
function runTask(t: Task) {
t.run();
}
runTask(new Task());
runTask(new Vehicle()); // Will be a compile time error
此行为还允许您不显式实现接口,例如,您可以为内联参数定义接口,并且任何满足合同的类都将兼容,即使它们没有显式实现任何接口:
function runTask(t: { run(): void }) {
t.run();
}
runTask(new Task());
runTask(new Vehicle());
从个人角度来说,来自C#,这一开始看起来很疯狂,但是当谈到可扩展性时,这种类型检查方式可以提供更大的灵活性,一旦你习惯它,你就会看到它的好处。
以上是关于为什么TypeScript中的类允许使用duck typing的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript对于Duck类型和模块命名空间的应用实战
TypeScript Duck Typing,未将属性字符串显示为数字错误
使用类中的构造函数的Typescript将不允许使用new关键字