我在查找TypeScript类和具有相同名称的接口之间看似特殊关系的任何明确文档或解释时遇到了一些麻烦。
代码:
// 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;
}
答案 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 年,可能只是过时了。