为什么交集类型包含冲突类型?

时间:2017-03-11 13:12:25

标签: typescript

给出两个具有冲突成员类型的接口:

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.

可以定义包含AB的交叉点类型:

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

是否存在技术原因,交叉类型在定义时不报告冲突?

1 个答案:

答案 0 :(得分:3)

type个操作数can be type parameters; interface... extends操作数必须是具体类型。

这种区别使typeinterface更灵活(它几乎是type的动机)。

一个结果是type运算符无法提前知道其完整的成员类型集,因此无法检测到此示例之类的冲突。

To quote Anders Hejlsberg

  

现在,操作数的类型参数的能力也很深   影响运算符的(可能的)语义。特别是   运算符必须始终为任何两个未知的操作数工作   成员集,因为它不可能有意义地报告错误   在类型实例化期间(即当真实类型被替换时)   类型参数)。这就产生了与...之间的差异。   并扩展。因为我们总是知道实际的类型   可以做更多检查和禁止我们认为错误的结构   经典的OOP观点。例如,我们可以在属性时出错   同名但不同的类型与extends冲突,而我们   用&。

合并(即交叉)他们的类型

有关详细信息,请参阅Github issue with a similar questionpull request for intersection types