官方文档的解释是:
联合类型表示一个值可以是几种类型之一例如:
type name = string | number
let myName1: name = '张三' // 正确
let myName2: name = 0 // 正确
从结果上看,这样的解释是没问题的,但是个人认为换种解释可能会更好:
联合类型表示一个值至少包含几种类型之一,且不能拥有几种类型都未规定的属性。这种解释和官网文档的解释可能存在有本质区别。
请看以下示例:
interface baseA {
name: string,
age: number
}
interface baseB {
addres: string
}
示例分析:
接口baseA表示一个对象,其只具有string类型的name属性和一个number类型的age属性。
接口baseB表示一个对象,其只具有string类型的addres属性
那么:
// 表达式A
const stu: baseA | baseB = {
name: '张三',
addres: '北京'
}
上面这段代码按官网文档的解释来分析,是无法通过的。比较baseA,少一个age属性;比较baseB,多一个name属性。但是,结果是可以通过的。
结果分析:
这和TS类型兼容性有关系。
类型兼容
阅读官网文档后确认,只有目标类型的成员会被检查是否兼容,此处的目标类型是
baseA和baseB,这个比较过程是递归进行的。
在上面的关于联合类型示例代码中:
在检查比较baseB时,由于只会检查作为目标类型的baseB,所以stu自身额外的name属性不会被报错。但是需要注意的是,name属性也是在baseA类型种有声明过,所以在声明对象字面量时才不会报错。
// 表达式A
const stu: baseA | baseB = {
name: '张三',
addres: '北京',
kkkk: ''
}
stu中存在有kkk属性,而baseA和baseB都未规定过该属性,所以这个表达式不会被通过,会报错多余了一个kkk属性
再来看一个示例1:
interface base{
name: string
age:number
}
function showAsdw(params:base) {
console.log('测试运行', params)
}
showAsdw({
name:'张三',
age: 12,
addres: ''
}) // ERROR 只能指定已知的属性,而 base中没有规定 addres
上面这个代码都不难理解,简单分析下,在调用showAsdw函数时,可以很明确的知道它需要的是一个base类型,那么在声明对象字面量时就会去对比base类型,发现不符合规定的属性或类型时,便会报错。
再看示例2
interface base{
name: string
age:number
}
function showAsdw(params:base) {
console.log('测试运行')
}
const stu11 = {
name: '张三',
age: 24,
addres: '地址是'
}
showAsdw(stu11) // 输出 测试运行
从逻辑上来看,示例1和示例2并无区别,只是示例2在进行类型校验时和示例略有不同。
一丶首先,在声明对象字面量stu11时,没有指定类型(ts会进行类型推断),所以不会报错;
二丶然后再调用showAsdw函数时,因为实际stu11已经有了类型(推断出的类型),那么就会去和目标类型进行对比,也就是base,在这个过程中,并不会对stu11额外的属性报错,这便是类型兼容。
总结
到这里再去结合类型兼容去看上面联合类型的示例就好理解了。
一丶在声明stu对象字面量时,就已知它最起码需要符合的类型,所以在此时声明没有规定的属性就会报错,例如kkkk。
二丶声明完成后,将stu和baseA、baseB进行对比,此时后者是目标类型,所以stu在分别进行单独比较时便不会因为额外的属性而报错