给定两个具有冲突成员类型的接口:
interface A { x: number }
interface B { x: string }
无法定义扩展以下两者的接口:
interface I extends A, B
// error TS2320: Interface 'I' cannot simultaneously extend types 'A' and 'B'.
// Named property 'x' of types 'A' and 'B' are not identical.
它是可能的,以限定包括交叉路口类型A和B:
let c = A & B
type C = A & B 
// no type errors
虽然无法创建这种类型的实例:
let withNumber: C = { x: 10 }
error TS2322: Type '{ x: number; }' is not assignable to type 'A & B'.
Type '{ x: number; }' is not assignable to type 'B'.
Types of property 'x' are incompatible.
Type 'number' is not assignable to type 'string'.
let withString: C = { x: "foo" }
// The same type error, with `number` and `string` reversed
交叉类型在定义时不报告冲突是否存在技术原因?
type操作数可以是类型参数;interface... extends操作数必须是具体类型。
这种区别type比interface(这几乎是 的动机type)更灵活。
一个后果是type操作员无法提前知道其完整的成员类型集,因此无法检测到与此示例类似的冲突。
现在,操作数作为类型参数的能力也深深地影响了操作符的(可能的)语义。特别是,操作符必须始终为具有未知成员集的任何两个操作数工作,因为在类型实例化期间(即,当实际类型替换类型参数时)不可能有意义地报告错误。这导致了 & 和 extends 之间的差异。因为实际类型总是通过 extends 知道的,所以我们可以做更多的检查并禁止我们从经典 OOP 角度认为错误的构造。例如,当同名但不同类型的属性与 extends 冲突时,我们可能会出错,而我们将它们的类型与 & 合并(即相交)。
有关更多信息,请参阅Github 问题中的类似问题和相交类型的拉取请求。
| 归档时间: | 
 | 
| 查看次数: | 2184 次 | 
| 最近记录: |