TypeScript 類型保護
本節(jié)介紹的類型保護 TypeScript 類型檢查機制的第二個部分,我們可以通過 typeof
、instanceof
、in
和 字面量類型
將代碼分割成范圍更小的代碼塊,在這一小塊中,變量的類型是確定的。
1. 慕課解釋
類型保護是指縮小類型的范圍,在一定的塊級作用域內(nèi)由編譯器推導(dǎo)其類型,提示并規(guī)避不合法的操作。
2. typeof
通過 typeof
運算符判斷變量類型,下面看一個之前介紹函數(shù)重載時的例子:
function reverse(target: string | number) {
if (typeof target === 'string') {
target.toFixed(2) // Error,在這個代碼塊中,target 是 string 類型,沒有 toFixed 方法
return target.split('').reverse().join('')
}
if (typeof target === 'number') {
target.toFixed(2) // OK
return +[...target.toString()].reverse().join('')
}
target.forEach(element => {}) // Error,在這個代碼塊中,target 是 string 或 number 類型,沒有 forEach 方法
}
代碼解釋:
第 2 行,通過 typeof 關(guān)鍵字,將這個代碼塊中變量 target 的類型限定為 string 類型。
第 6 行,通過 typeof 關(guān)鍵字,將這個代碼塊中變量 target 的類型限定為 number 類型。
第 11 行,因沒有限定,在這個代碼塊中,變量 target 是 string 或 number 類型,沒有 forEach 方法,所以報錯。
3. instanceof
instanceof 與 typeof 類似,區(qū)別在于 typeof 判斷基礎(chǔ)類型,instanceof 判斷是否為某個對象的實例:
class User {
public nickname: string | undefined
public group: number | undefined
}
class Log {
public count: number = 10
public keyword: string | undefined
}
function typeGuard(arg: User | Log) {
if (arg instanceof User) {
arg.count = 15 // Error, User 類型無此屬性
}
if (arg instanceof Log) {
arg.count = 15 // OK
}
}
代碼解釋:
第 12 行,通過 instanceof 關(guān)鍵字,將這個代碼塊中變量 arg 的類型限定為 User 類型。
第 16 行,通過 instanceof 關(guān)鍵字,將這個代碼塊中變量 arg 的類型限定為 Log 類型。
4. in
in
操作符用于確定屬性是否存在于某個對象上,這也是一種縮小范圍的類型保護。
class User {
public nickname: string | undefined
public groups!: number[]
}
class Log {
public count: number = 10
public keyword: string | undefined
}
function typeGuard(arg: User | Log) {
if ('nickname' in arg) {
// (parameter) arg: User,編輯器將推斷在當(dāng)前塊作用域 arg 為 User 類型
arg.nickname = 'imooc'
}
if ('count' in arg) {
// (parameter) arg: Log,編輯器將推斷在當(dāng)前塊作用域 arg 為 Log 類型
arg.count = 15
}
}
代碼解釋:
第 12 行,通過 in 關(guān)鍵字,將這個代碼塊中變量 arg 的類型限定為 User 類型。
第 17 行,通過 in 關(guān)鍵字,將這個代碼塊中變量 arg 的類型限定為 Log 類型。
5. 字面量類型保護
用字面量類型那一節(jié)的例子改造一下來介紹字面量類型保護:
type Success = {
success: true,
code: number,
object: object
}
type Fail = {
success: false,
code: number,
errMsg: string,
request: string
}
function test(arg: Success | Fail) {
if (arg.success === true) {
console.log(arg.object) // OK
console.log(arg.errMsg) // Error, Property 'errMsg' does not exist on type 'Success'
} else {
console.log(arg.errMsg) // OK
console.log(arg.object) // Error, Property 'object' does not exist on type 'Fail'
}
}
代碼解釋:
第 15 行,通過布爾字面量,將這個代碼塊中變量 arg 的類型限定為 Success 類型。
第 18 行,通過布爾字面量,將這個代碼塊中變量 arg 的類型限定為 Fail 類型。
6. 小結(jié)
類型保護就是讓編譯器幫助我們縮小類型范圍,在編譯階段規(guī)避掉一些不必要的錯誤,提高代碼質(zhì)量。