1.TS的联合类型(并集)
但是对于 const f1 = (a:number | string) = > { ...... },如果不做处理的话,在方法体内就既不能把a当做number使用,也不能把a当做string使用。所以想要使用联合类型的话,就必须想办法把类型区分开来。
JS中区分类型的方法(JS中的类型收窄(Narrowing)):
1.使用typeof来区分类型
const f1 = (a:number | string) => {
if(typeof a === 'number') {
a.toFixed(2) // 此时a类型为number
} else if (typeof a === 'string') {
a.split(',') // 此时a类型为string
}
}
typeof的局限性:
2.使用instanceof来区分类型
const f1 = (a:Date | Date[]) => {
if(a instanceof Date) {
a // 此时a为Date
} else {
a // 此时a为Date[]
}
}
instanceof的局限性:
1.不支持string、number、boolean...
在TS中使用 if(a instanceof String)会报错
解决该问题可采用与 typeof 混合使用:
const f1 = (a:string | Date | Date[]) => {
if ( typeof a === 'string') {
a // 此时a为string
} else if ( a instanceof Date) {
a // 此时a为Date
} else {
a // 此时a为Date[]
}
}
2.不支持TS独有的类型
type Person = {
name:string
}
type Animal = {
age:number
}
const f1 = (a:Person | Animal) {
if(a instanceof Person) { // 报错
a
}
}
3.使用 in 来收窄类型
type Person = {
name:string
}
type Animal = {
age:number
}
const f1 = (a:Person | Animal) {
if('name' in a) {
a // 此时a为Person
} else if ('age' in a) {
a // 此时a为Animal
}
}
in 的局限性: 只适用于部分对象
4.使用JS中判断类型的函数来区分
5.使用JS中的逻辑来收窄类型
总结:无论使用JS中的何种区分类型的方法,都会有相应的局限性,故应该使用TS中的区分类型的完全方法。
TS中区分类型的方法:
1.类型谓词/类型判断 is:
type Rect = {
height:number,
width:number
}
type Circle = {
center: [number,number],
radius: number
}
type Shape = Rect | Circle
const f1 = (s:Shape) => {
if (isRect(s)) {
console.log(s.height) // 此时s为Rect
} else if (isCircle(s)) {
console.log(s.center) // 此时s为Circle
}
}
function isRect (x:Rect | Circle): x is Rect {
return 'height' in x && 'width' in x
}
function isCircle (x:Rect | Circle): x is Circle {
return 'center' in x && 'radius' in x
}
is的优点:支持所有TS类型;is的缺点:写法麻烦
2.可辨别联合x.kind:
type Circle = {kind:'Circle', center:[number,number]}
type Square = {kind:'Square',sideLength:number}
type Shape = Circle | Square
const f1 = (a:Shape) => {
if (a.kind === 'Circle') {
a // 此时a为Circle
} else if (a.kind === 'Square') {
a // 此时a为Square
}
}
优点:让复杂类型的收窄变成简单类型的对比
要求:T=A | B | C | D | ...
1. A、B、C、D...有相同属性kind或其他 ;2.kind的类型是简单类型 ;3.各类型中的kind可区分 则称T为可辨别联合(一句话总结:同名、可辨别的简单类型的key)
3.类型断言as:
用于已知参数类型
什么是所有类型的联合?(所有类型不包括never/unknown/any/void)
答案:unknown
any为什么不是所有类型的联合?
用反证法可以证明
const f1 = (a:number | string) {
a.toFixed(2) // error
a.split(',') // error
// 在未进行类型收窄前只能使用类型共有的方法
}
const f1 = (a:any) {
a.toFixed()
a.join()
a.split(' ')
// 可以使用任意类型的方法
}
TS中绝大部分规则对any不生效
unknown才是所有类型的联合
const f1 = (a:unknown) => {
if(typeof a === 'string') {
a
}else if (a instanceof Date) {
a
}
}