一个值的多项类型要求

交类型是类型系统中表达“同时满足”的构造,通常写作A∩B或A & B。一个值若具有这个类型,就须同时符合A、B所描述的要求。它是在编译或形式推理中描述值的性质,不是运行时取两个集合容器共同元素的运算;同一符号在不同语言里也未必对应完全相同的规则。

例如,一个接口要求对象提供字符串名称,另一个接口要求提供序列化方法,两者的交类型要求同一个对象同时具备这两项能力。使用者可以依相应的类型规则,把它用于需要任一接口的位置。这里组合的是约束,而不是自动制造一个对象,也不是把两个独立对象绑定成一对。

参考:[1] [2]

引入、使用与函数性质

在典型的纯类型规则中,若同一表达式在同一上下文下可被证明具有A,也可被证明具有B,就能引入A与B的交;已知它具有交类型,则能取出其中任一项保证。相应的子类型观点是,A∩B比A、B都更具体。但某个实际系统是否允许把这些规则直接用于任意表达式,还取决于求值方式与副作用。

交类型并不限于对象字段。一个函数既把自然数映射到自然数,又把正自然数映射到正自然数,就能用两个函数类型的交记录这两种行为。调用时依据实参已知的类型利用适用保证。这不同于只说结果“可能属于两种类型之一”,也不必表示程序中存在两个函数实现。

参考:[3]

与联合和字段合并的差别

联合类型A | B表达可属于A或B;不知道实际属于哪一支时,只能安全使用共同支持的操作,或先通过检查缩小范围。交类型表达的是两项约束都成立,因此给使用者更多保证,同时对提供值的一方提出更严格的要求。把联合理解成“合并所有可用字段”,会混淆这两种方向。

TypeScript用&组合对象类型,看起来像把字段放到一起,但同名字段的要求不会简单以后者覆盖前者。若一边要求name为字符串,另一边要求它为数值,交类型中的该属性须同时满足两种要求,最终会成为never。官方手册还区分了交类型与接口扩展或声明合并的冲突处理;名称相近不表示检查过程相同。

参考:[1] [2]

表达能力、推断与副作用

丰富的交类型规则会增加类型赋予和类型推断的难度,不能仅凭类型符号就断言某种推断算法总能终止并找出最佳类型。不同系统通过限制允许的构造、增加类型标注或改变检查方式取得实用性。Davies与Pfenning在2000年的研究区分可综合出类型的表达式与按已给类型检查的表达式,以双向检查支持其特定语言。

同一研究还指出,把通常的交类型规则直接搬到有可变引用等计算副作用的语言,可能破坏可靠性;他们对交类型引入施加类似值限制的条件,并调整子类型规则。这说明交类型不是可脱离语言语义单独安装的语法便利。介绍某语言的交类型时,必须说明其对象模型、可变性与检查规则,而不能把理论系统和工程实现视为同一个系统。

参考:[3]