为什么私有财产是接口的一部分?

时间:2019-10-09 18:22:02

标签: typescript

请考虑以下内容:

class X  {
    bar() {
        return "bar"
    }
    constructor(private readonly x: number){}
}

interface Y extends X {
}


const f = (y: Y) => { console.log(y.bar()); }

f({ bar: () => "tavern"});

它不编译,因为缺少x

f({ bar: () => "tavern", x: 1});

由于x不是私有的而无法编译。

重新编写代码,以便可以声明x私有

class Y implements X {
    bar() {
        return "tavern"
    }
    private x = 1;
}

被拒绝,因为“类型具有单独的声明”。

我发现的唯一解决方案是从构造函数中删除private

我真正想做的是第一件事:我不在乎类的私有属性,尤其是不在乎在构造函数中声明的私有成员。

我的两个问题是:

  1. 为什么会这样?
  2. 如果可以的话,我该怎么办,而不必担心私有财产?

2 个答案:

答案 0 :(得分:2)

Microsoft Typescript团队的开发负责人Ryan Cavanaugh,wrote

  

允许私有字段丢失将是巨大的   问题,而不是一些琐碎的健全性问题。

     

考虑以下代码:

class Identity {
  private id: string = "secret agent";
  public sameAs(other: Identity) {
    return this.id.toLowerCase() === other.id.toLowerCase();
  }
}

class MockIdentity implements Identity {
  public sameAs(other: Identity) { return false; }
}
     

MockIdentityIdentity的公共兼容版本,但   尝试将其作为一个非模拟使用时,将在sameAs中崩溃   复制与模拟副本互动。

糟透了。这很有意义,但是很烂。

但是,我找到了一种解决方法来解决我的问题:

type Public<T> = {
    [P in keyof T]: T[P];
};

class X  {
    bar() {
        return "bar"
    }
    constructor(private readonly x: number){}
}

interface Y extends Public<X> { }

const f = (y: Y) => { console.log(y.bar()); }

f({ bar: () => "tavern"});

这使我能够可靠地模拟复杂类型,而不必也模拟私人数据。

这在测试环境中是安全的 ,其中模拟实例和真实实例永远不会交互。

答案 1 :(得分:-3)

接口不应扩展类。接口定义对象的特征(可饮用的接口),类定义什么是对象(水类)。 所以我建议您定义一个接口并让您的类实现该接口