子类型及其超类型的交集是否与子类型相同?
Is intersection of a subtype and its supertype the same as the subtype?
给定以下 TypeScript 代码:
interface A { /* ... */ }
interface B extends A { /* ... */ }
type Mystery = A & B;
Mystery
类型的对象应该具有A
的所有属性和B
的所有属性,因为它是交集类型。 B
类型的对象应该已经具有 A
的所有属性,因为 B extends A
.
根据这些定义,类型 Mystery
和类型 B
之间有区别吗?
初步近似,如果B extends A
,则A & B
和B
是相同的。编译器甚至会考虑 A & B
和 B
相互赋值:
function foo<A, B extends A>(u: B, m: A & B) {
u = m; // okay
m = u; // okay
}
虽然不完全相同:
function foo<A, B extends A>(u: B, m: A & B) {
var v: B;
var v: A & B; // error, not considered identical
}
在实践中,编译器会以不同的方式对待 A & B
和 B
。其中一些是被视为错误或设计限制的编译器实现细节;我得去挖掘这些。
但是 A & B
和 B
很容易不同的一个特定地方与调用签名的交集如何被解释为 overloaded 可以以多种方式调用的函数有关,而具有调用签名的接口扩展往往只是 覆盖 父接口调用签名并且只能以一种方式调用。例如:
interface A { method(p: any): void }
interface B extends A { method(): void }
这是允许的,因为 functions of fewer parameters are assignable to functions of more parameters。类型 B
只看到零参数方法,所以你得到以下行为:
declare const a: A;
a.method(0); // okay
declare const b: B;
b.method(); // okay
b.method(0); // error!
由于 method()
在 B
中被重写,因此 b.method()
没有参数是错误的(即使零参数方法可分配给多参数方法,您仍然不能在没有警告的情况下故意调用带有太多参数的函数。
将此与路口进行比较:
type Mystery = A & B;
declare const m: Mystery;
m.method(""); // okay
m.method(); // okay
如果您检查 m.method
,您会发现它有两个重载:
// 1/2 method(p: any): void
// 2/2 method(): void
因此两种方式都可以调用。
给定以下 TypeScript 代码:
interface A { /* ... */ }
interface B extends A { /* ... */ }
type Mystery = A & B;
Mystery
类型的对象应该具有A
的所有属性和B
的所有属性,因为它是交集类型。 B
类型的对象应该已经具有 A
的所有属性,因为 B extends A
.
根据这些定义,类型 Mystery
和类型 B
之间有区别吗?
初步近似,如果B extends A
,则A & B
和B
是相同的。编译器甚至会考虑 A & B
和 B
相互赋值:
function foo<A, B extends A>(u: B, m: A & B) {
u = m; // okay
m = u; // okay
}
虽然不完全相同:
function foo<A, B extends A>(u: B, m: A & B) {
var v: B;
var v: A & B; // error, not considered identical
}
在实践中,编译器会以不同的方式对待 A & B
和 B
。其中一些是被视为错误或设计限制的编译器实现细节;我得去挖掘这些。
但是 A & B
和 B
很容易不同的一个特定地方与调用签名的交集如何被解释为 overloaded 可以以多种方式调用的函数有关,而具有调用签名的接口扩展往往只是 覆盖 父接口调用签名并且只能以一种方式调用。例如:
interface A { method(p: any): void }
interface B extends A { method(): void }
这是允许的,因为 functions of fewer parameters are assignable to functions of more parameters。类型 B
只看到零参数方法,所以你得到以下行为:
declare const a: A;
a.method(0); // okay
declare const b: B;
b.method(); // okay
b.method(0); // error!
由于 method()
在 B
中被重写,因此 b.method()
没有参数是错误的(即使零参数方法可分配给多参数方法,您仍然不能在没有警告的情况下故意调用带有太多参数的函数。
将此与路口进行比较:
type Mystery = A & B;
declare const m: Mystery;
m.method(""); // okay
m.method(); // okay
如果您检查 m.method
,您会发现它有两个重载:
// 1/2 method(p: any): void
// 2/2 method(): void
因此两种方式都可以调用。