联合类型

有时可能出现一个变量需支持多种类型的情况

1
2
3
4
5
6
7
8
9
10
// 联合类型,每个类型间用|断开
let phone:number|string
phone = 13000000000 // OK
phone = "130-0000-0000" // OK
phone = false // 不OK,联合类型里不包含boolean

// 函数中也可以使用联合类型
const fn = function(type:number|boolean):boolean {
return !!type
}

交叉类型

有时可能出现需要将两个类型(接口)合并的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface People {
name:string,
age:number
}

interface Place {
address:string
}

// man的类型是People和Place的总和
const live = (man:People&Place):void=> {
console.log(man)
}

// 传入的参数需要同时拥有People和Place的属性,name、age和address
live({
name:"yajue",
age:24,
address:"下北泽"
})

类型断言

告诉TS某个变量一定是某个类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let fn = (str:number|string):void=> {
// 当num为number时,它是不存在length属性的
// 可以使用类型断言,告诉TS,num是string
console.log((str as string).length)
}

// 非必要不使用类型断言,比如此处无法保证num一定是string
// 滥用类型断言可能导致运行时错误
fn("12345") // ->5
fn(67890) // ->undefined


interface A {
foo:string
}
interface B {
bar:string
}

let fn2 = (foobar:A|B):void=> {
// 复杂类型也可以断言
console.log((foobar as A).foo)
}

fn2({foo:"yajue"}) // ->"yajue"
fn2({bar:"yjsp"}) // ->undefined

类型断言常用在使用服务器环境全局变量的场景中

1
2
3
4
// 报错,因为window没有abc属性
window.abc = 123
// 临时断言为any,在any类型的变量上,访问任何属性都是允许的
(window as any).abc = 123

类型断言只能欺骗TS编译器,并不会真的去转换类型

1
2
3
4
5
6
const fn = (type:any):boolean=> {
return type as boolean
}

console.log(fn(1)) // ->1
console.log(fn("yajue")) // ->"yajue"

也可以使用as const对字面量进行断言,它与用const定义常量是有区别的

1
2
3
4
5
6
7
8
9
10
11
12
let name1 = "nyn" as const
const name2 = "yajue"

name1 = "mouse" // 无法修改,因为name1被断言为了字面量"nyn"
name2 = "yjsp" // 无法修改,因为name2是常量


let a1 = [10, 20] as const
const a2 = [10, 20]

a1.unshift(30) // 无法修改,因为a1被断言为了字面量[10, 20]
a2.unshift(30) // 可以修改,因为没有改变a2的引用