一,前言
上一篇介紹了TS高級類型-交叉類型
本篇介紹另一個TS高級類型-聯合類型
聯合類型並不陌生,之前已經接觸過多次了
二,簡單的聯合類型
聯合類型:
聲明時,類型可能爲多個類型中的一種,但不能確定是哪一種
let a: number | string = 1
let b: number | string = "1"
三,字面量聯合類型
字面量類型:
不僅限定變量類型,還限定變量的取值範圍
字面量聯合類型:
let c: 1 | 2 | 3 = 1
let d: '1' | '2' | '3' = '1'
四, 對象聯合類型
還是使用之前的例子:
// 對象聯合類型
// 聲明兩個接口:包含相同和不同方法各一個
interface JavaInterface {
helloJava(): void
build(): void
}
interface JavaScriptInterface {
helloJavascript(): void
build(): void
}
// 定義兩個類,分別實現兩個接口
class Java implements JavaInterface {
helloJava() {}
build() {}
}
class JavaScript implements JavaScriptInterface {
helloJavascript() {}
build() {}
}
// 定義枚舉Type
enum Type { Strong, Week }
// 根據類型獲取實例
function getLanguage(type: Type) {
let lang = type === Type.Strong ? new Java() : new JavaScript()
return lang
}
根據類型獲取實例的getLanguage方法中,lang爲聯合類型
這時,對象類型並不能確定,到底是Java還是JavaScript
所以此時,是不能訪問helloJava和helloJavascript的,只能訪問共有的build方法
五,可區分的聯合類型
這種模式本質上是結合聯合類型和字面量類型的一種類型保護方法
原理:
如果一個類型是多個類型的聯合類型,且多個類型間有一個公共屬性
那麼,就可以利用這個公共屬性,創建不同的類型保護區塊
// 聲明兩個接口Square,Rectangle,都有kind屬性表示類型
// 正方形
interface Square {
kind: 'square'
side: number // 邊長
}
// 長方形
interface Rectangle {
kind: 'rectangle'
width: number // 寬
height: number // 高
}
// 使用類型別名聲明Square和Rectangle的聯合類型Shape
type Shape = Square | Rectangle
// 計算面積:利用兩種類型共有的kind屬性,創建不同的類型保護區塊
function area(s: Shape) {
switch (s.kind){
case 'square':
return s.side * s.side
case 'rectangle':
return s.height * s.width
}
}
添加Circle
// 正方形
interface Square {
kind: 'square'
side: number // 邊長
}
// 長方形
interface Rectangle {
kind: 'rectangle'
width: number // 寬
height: number // 高
}
// 圓
interface Circle {
kind: 'circle'
r: number // 半徑
}
type Shape = Square | Rectangle | Circle
// 計算面積:利用兩種類型共有的kind屬性,創建不同的類型保護區塊
function area(s: Shape) {
switch (s.kind){
case 'square':
return s.side * s.side
case 'rectangle':
return s.height * s.width
}
}
這時發生一個問題:
area方法中並未添加circle的計算邏輯,但代碼沒有報錯
如果此時運行代碼將得到結果爲undefined:
console.log(area({kind: 'circle', r: 1})) // undefined
這種情況需要使用TS進行約束:
1,爲函數指定明確的返回值類型
爲函數指定明確的返回值類型,那麼TS就會判斷Switch塊中是否包含了所有分支
2,利用never類型
在switch-default中,將未捕捉到的類型賦值給never,檢查s是否是never類型
在default中檢查未被之前case捕捉到的類型是否爲never類型
如果s是never類型,說明前面的所有分支都被覆蓋了,這個分支永遠不會走到
如果s不是never類型,說明前面的分支有遺漏,需要補上這個分支
正確的代碼:
// 正確的寫法
function area(s: Shape) {
switch (s.kind){
case 'square':
return s.side * s.side
case 'rectangle':
return s.height * s.width
case 'circle':
return Math.PI * s.r ** 2
default:
return ((e: never) => {
throw new Error(e)
})(s)
}
}
console.log(area({kind: 'circle', r: 1})) // 3.141592653589793
六,結尾
本篇介紹了TS高級類型-聯合類型,包括:
1,簡單的聯合類型
2,字面量聯合類型
3,對象聯合類型
4,可區分的聯合類型
5,TS對聯合類型的約束