首页 文章

为什么TypeScript中的类允许使用duck typing

提问于
浏览
14

在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());

但与此同时我期望 compilation error ,因为 VehicleTask 没有任何共同之处 .

理智的用法可以通过显式接口定义来实现:

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试图引入静态检查,类,接口等 . 但在我看来,类实例的鸭子类型看起来相当混乱和容易出错 .

1 回答

  • 14

    这是结构类型的工作方式 . Typescript有一个结构类型系统,可以最好地模拟Javscript的工作方式 . 由于Javascript使用duck typing,因此任何定义 Contract 的对象都可以在任何函数中使用 . 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
    

    此行为还允许您不显式实现接口,例如,您可以为内联参数定义接口,并且任何满足 Contract 的类都将兼容,即使它们没有显式实现任何接口:

    function runTask(t: {  run(): void }) {
        t.run();
    }
    
    runTask(new Task());
    runTask(new Vehicle());
    

    从个人角度来说,来自C#,这一开始看起来很疯狂,但是当谈到可扩展性时,这种类型检查方式可以提供更大的灵活性,一旦你习惯它,你就会看到它的好处 .

相关问题