>[success] # 類型守衛
~~~
1.類型守衛的作用在于觸發類型縮小。實際上,它還可以用來區分類型集合中的不同成員
2.類型守衛包括switch、字面量恒等、typeof、instanceof、in 和自定義類型守衛
簡單說當一個類型是多種可能時例如'any','unknown','聯合類型' 等在邏輯判斷時候要具體到其唯一子集可能性
2.1.類型判斷:typeof
2.2.實例判斷:instanceof
2.3.屬性判斷:in
2.4.字面量相等判斷:==, ===, !=, !==
~~~
>[danger] ##### 沒有使用類型守衛案例
~~~
1.通過斷言,斷言其子類型做到縮小范圍不報錯,雖然這種形式也可以但是需要大量斷言來區分類型
~~~
~~~
const getRandomValue = (list: (string | number)[]) => {
const randomNumber = Math.random() * 10
if (randomNumber > 5) return list[0]
else return list[1]
}
const item = getRandomValue([1, 'w'])
// 直接這些寫會報錯
// 首先第一個問題是返回值的類型不確定是字符還是數字
// 數字是沒有length 屬性的所以這么寫的判斷ts 會報錯的
// if(item.length){
// console.log(item.length)
// }else{
// console.log(item.toFixed())
// }
// 解決第一種使用類型斷言
// 缺點 每一個item 都要使用對應的類型斷言
if ((item as string).length) {
console.log((item as string).length)
} else {
console.log((item as number).toFixed())
}
~~~
>[danger] ##### 使用typeof 進行類型守衛
~~~
1.type of ,但只能針對"number","string","boolean"或"symbol",反過來,當聯合類型的成員不可枚舉,
比如說是字符串、數字等原子類型組成的集合,這個時候就需要使用 typeof。
2.下面案例為例'判斷了string'類型else 自動判斷就是,number 類型,如果是判讀是非這四種類型,else
還需要要自己處理
3.下面代碼如果'return params.length ? params.length : params 這么寫會報錯' 這就是為什么要類型守衛縮小類型
~~~
~~~
function getType(params: string | number) {
// return params.length ? params.length : params 這么寫會報錯
if (typeof params === 'string') {
return params.length
} else {
return params
}
}
~~~
>[danger] ##### instanceof 針對類 -- 縮小范圍
~~~
1.如果是類的話使用 'instanceof'
~~~
~~~
class Dog {
wang = 'wangwang'
}
class Cat {
miao = 'miaomiao'
}
const getName = (animal: Dog | Cat) => {
if (animal instanceof Dog) {
return animal.wang
} else (animal instanceof Cat) {
return animal.miao
}
}
const cat = new Cat()
getName(cat)
~~~
>[danger] ##### 字面量恒等
~~~
1.如果是字面量這種聯合類型可以使用具體值去比較
2.也可用switch 來縮小類型 代替if
~~~
~~~
function getType(params: 'a' | 1) {
if (params === 'a') {
return params.length
}
return params
}
~~~
* 案例二
~~~
type Foo = {
kind: 'foo'; // 字面量類型
foo: number;
};
type Bar = {
kind: 'bar'; // 字面量類型
bar: number;
};
function doStuff(arg: Foo | Bar) {
if (arg.kind === 'foo') {
console.log(arg.foo); // ok
console.log(arg.bar); // Error
} else {
console.log(arg.foo); // Error
console.log(arg.bar); // ok
}
}
~~~
>[danger] ##### 獲取value 值 -- in
~~~
1.不能直接通過'. '操作符獲取 對象值 需要 用 in
~~~
~~~
type Info = {
name: string
age: number
}
type Person = {
name: string
}
function getName(info: Info | Person) {
// if(info.age){} // 報錯
if ('age' in info) {
return info.age
} else {
return info.name
}
}
~~~
>[danger] ##### 自定義守衛 -- is
~~~
1.往往開發時候會吧一些判單同一封裝 像下面的例子雖然封裝了,但實際效果卻報錯
function isString(params: unknown) {
return typeof params === 'string'
}
function getName(params: number | string) {
// if(typeof params === "string") 可以的但是這種重復邏輯一般會封裝
if (isString(params)) {
return params.length // 報錯
}
}
~~~
* 正確寫法
~~~
1.這里的is 可以是任意類型,可以是自己定義的接口類型,這里是因為需求是string 類型,如果不做 is 類型,
TS 只能推斷出 isString 是一個返回布爾值的函數,而并不知道這個布爾值的具體含義'{形參} is {類型} 的語法結構'
~~~
~~~
function isString(params: unknown) :params is string{
return typeof params === 'string'
}
function getName(params: number | string) {
// if(typeof params === "string") 可以的但是這種重復邏輯一般會封裝
if (isString(params)) {
return params.length
}
}
~~~
- TypeSprict -- 了解
- TS-- 搭建(一)webpack版本
- TS -- 搭建(二)直接使用
- TS -- 基本類型
- ts -- 類型推導和字面量類型
- ts -- 類型擴展和類型縮小
- ts -- any場景
- ts -- 使用unknown 還是 any
- ts -- any/never/unknown
- ts -- 斷言
- ts -- 類型大小寫疑惑
- ts -- 數組類型 [] 還是泛型疑惑
- TS -- 枚舉
- 外部枚舉
- TS -- 函數
- ts -- 重載作用
- ts -- 05 this is
- 解構
- TS -- 接口
- 繞過接口的多余參數檢查
- Interface 與 Type 的區別
- TS -- 類
- ts -- 類作為類型
- TS -- 交叉和聯合 類型
- ts -- 交叉類型
- ts -- 聯合類型
- ts -- 交叉和聯合優先級
- ts -- 類型縮減
- TS -- 什么是泛型
- ts -- 泛型函數表達式/函數別名/接口
- ts -- 泛型類
- ts -- extends 泛型約束
- ts -- 泛型new
- ts -- Ts的泛型
- TS -- 縮小類型詳解類型守衛
- TS -- 類型兼容性
- TS -- 命名空間與模塊化
- ts -- 模塊化
- ts -- 命名空間
- TS -- 工具方法
- Record -- 一組屬性 K(類型 T)
- Exclude -- 從聯合類型中去除指定的類
- Extract -- 聯合類型交集
- NonNullable -- 從聯合類型中去除 null 或者 undefined
- Partial -- 將所有屬性變為可選
- Required -- 所有屬性變為必填
- Readonly -- 所有屬性只讀
- Pick -- 類型中選取出指定的鍵值
- Omit -- 去除指定的鍵值