TypeScript是否支持ducktype?

时间:2016-05-20 13:56:51

标签: typescript

我看到有关此的矛盾信息。 https://basarat.gitbooks.io/typescript/content/docs/classes.html(转到继承部分)这里说它支持但是我看到我的代码无法在TypeScript中编译playGround

class Point{
    x:number; 
    y:number;
    constructor(x:number, y:number){
    this.x = x;
    this.y = y ;    
    }

    add(point:Point){
     return new Point(this.x + point.x , this.y + point.y);
    }
}

class Point3D extends Point{
    z:number;
    constructor(x:number, y:number, z:number){
        super(x,y);
        this.z = z;
    }

    add(point3d:Point3D){
        // Error does not support duct type.
        var point2D = super.add( {point3d.x, point3d.y}); 
        return new Point3D(point2D.x, point2D.y, this.z);
    }
}

4 个答案:

答案 0 :(得分:3)

在您的情况下不够好,只需按原样传递Point实例:

add(point3d:Point3D){
    // Error does not support duct type.
    //var point2D = super.add( {point3d.x, point3d.y}); 

    var point2D = super.add(point3d);

因为超级简单地接受点

add(point:Point){...

和Point3d是Point

class Point3D extends Point{

updated playground

如果我们想用完全强度的鸭子打字,我们应该介绍接口

interface IPoint{
    x:number; 
    y:number;
}

并在add方法中使用它

add(point:IPoint){
 return new Point(this.x + point.x , this.y + point.y);
}

最后,我们可以使用duck typing:

var point2D = super.add({x: point3d.x, y: point3d.y});

调整后的example is here

答案 1 :(得分:2)

TypeScript实际上不是duck typed,而是structurally typed。区别在于,鸭子打字只关心您在运行时访问的特定成员是否存在,而结构类型需要您完成您想要充当的对象的整个合同特定的接口/类型。

当您发送对象{x:point3d.x, y:point3d.y}时,TypeScript要求此对象在结构上与Point兼容,因为它没有添加方法,所以它不是。{ p>

答案 2 :(得分:1)

您正在尝试创建一个对象{x:number, y:number}并将其称为Point。但是,Point的类型为{x:number, y:number, add:(point:Point)=>Point}。如果你介绍一个'添加'匹配该签名的属性。

答案 3 :(得分:1)

这里有几件事情。

  1. 你的语法错了。如果您正在尝试创建对象,则{point3d.x, point3d.y}应为{x: point.x, y: point.y}
  2. 在这种情况下你不能使用ducktype,因为你的对象没有add方法(编译器会告诉你这个)。下面我创建了一个名为IPoint的接口来满足编译器。
  3. 请参阅我的解决方案:

    interface IPoint {
        x: number;
        y: number;
    }
    
    class Point{
        x:number; 
        y:number;
        constructor(x:number, y:number){
        this.x = x;
        this.y = y ;    
        }
    
        add(point:IPoint){
         return new Point(this.x + point.x , this.y + point.y);
        }
    }
    
    class Point3D extends Point{
        z:number;
        constructor(x:number, y:number, z:number){
            super(x,y);
            this.z = z;
        }
    
        add(point:Point3D){
            var point2D = super.add({x: point.x, y: point.y});
            return new Point3D(point2D.x, point2D.y, this.z);
        }
    }