TypeScript类与具有相同名称的接口之间的关系

时间:2017-03-27 20:16:10

标签: class typescript interface

我在查找TypeScript类和具有相同名称的接口之间看似特殊关系的任何明确文档或解释时遇到了一些麻烦。

  • 具有与班级同名的界面的重要性是什么?
  • 为什么与接口共享其名称的类会自动实现该接口?
  • 当类和接口具有相同的名称时,为什么编译器会抱怨我的getterly接口字段的getter实现,但如果名称不同,则接受实现?
  • 是否有解决这些问题的规范性文件?

代码:

// Co-named interface and class doesn't like readonly property implementation:

interface Foo {
  readonly x: number; // Error: Duplicate identifier 'x'
  y: number;
}

class Foo {
  get x(): number { // Error: Duplicate identifier 'x'
    return 0;
  }

  y = 1;
}

// Same as above, but different class name + explicit `implements`

class Bar implements Foo {
  get x(): number { // No error!
    return 0;
  }

  y = 1;
}

// Duplicating the first example, but explicitly implementing the co-named interface:

interface Baz {
  readonly x: number; // Error: Duplicate identifier 'x'
  y: number;
}

class Baz implements Baz {
  get x(): number { // Error: Duplicate identifier 'x'
    return 0;
  }

  y = 1;
}

2 个答案:

答案 0 :(得分:16)

模块will be merged中具有相同名称的接口:

interface Foo {
    x: number;
}

interface Foo {
    y: string;
}

let g = {} as Foo;
g.x; // OK
g.y; // OK

类声明创建both a constructor function as well as type declaration,这实际上意味着所有类都可以用作接口。

class Bar {
    y: number;
}

interface IBaz extends Bar { } // includes y: number

class CBaz implements Bar {
    y: number = 5;
}

因此,拥有一个具有相同名称的类和接口相当于具有两个具有相同名称的接口,并且如果接口的两个实例重新声明具有不同类型的相同成员,则会发生合并冲突。

奇怪的是,Typescript将允许这样做:

export interface Foo {
    readonly x: number;
}

export class Foo {
    readonly x: number = 3;
}

但它不会允许get x() { return 3; },尽管这两个都生成readonly x: number,所以我只能想象类型检查器在合并期间认为它们是不同的,即使它们在语义上是相同(这就是为什么你可以扩展接口并将readonly属性指定为getter函数)。

答案 1 :(得分:1)

这是访问者特有的限制,到目前为止,Typescript 团队出现了 unwilling to comment 问题。

class Foo {
  readonly x: number = 0;
}

class Bar extends Foo {}
interface Bar {
  readonly x: 2;
}

const bar = new Bar();
bar.x; // type is 2, no error

团队 commented“[w]属性是作为字段实现还是getter/setter对是实现细节,而不是类型的一部分,”但是这显然不是 Typescript 4.2 的情况:

class Baz extends Foo {
    // error: "'x' is defined as a property in class 'Foo',
    //         but is overridden here in 'Baz' as an accessor."
    get x() {
        return 2;
    }
}

我无法解释团队的回应。关于 getter/setter 不属于类型系统的评论来自 2015 年,可能只是过时了。

相关问题