给出两个具有冲突成员类型的接口:
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
是否存在技术原因,交叉类型在定义时不报告冲突?
答案 0 :(得分:3)
type
个操作数can be type parameters; interface... extends
操作数必须是具体类型。
这种区别使type
比interface
更灵活(它几乎是type
的动机)。
一个结果是type
运算符无法提前知道其完整的成员类型集,因此无法检测到此示例之类的冲突。
现在,操作数的类型参数的能力也很深 影响运算符的(可能的)语义。特别是 运算符必须始终为任何两个未知的操作数工作 成员集,因为它不可能有意义地报告错误 在类型实例化期间(即当真实类型被替换时) 类型参数)。这就产生了与...之间的差异。 并扩展。因为我们总是知道实际的类型 可以做更多检查和禁止我们认为错误的结构 经典的OOP观点。例如,我们可以在属性时出错 同名但不同的类型与extends冲突,而我们 用&。
合并(即交叉)他们的类型
有关详细信息,请参阅Github issue with a similar question和pull request for intersection types。