TypeScript類型斷言VS類型守衛(wèi)示例詳解
類型斷言
類型斷言有兩種寫法,分別為value as Type和<Type>value,它讓 TypeScript 編譯器將 value 當(dāng)作 Type 類型。類型斷言是一個(gè)編譯時(shí)特性,不進(jìn)行類型轉(zhuǎn)換,因此不會(huì)影響變量在運(yùn)行時(shí)的數(shù)據(jù)類型。如果某變量是 any 類型,但現(xiàn)在你知道它確切的數(shù)據(jù)類型,使用類型斷言能讓 IDE 有代碼提示的能力,也能讓 TypeScript 編譯器進(jìn)行類型檢查。
類型斷言的用法如下:
const age: any = 23.44;
const user: any = {age: 2}
// age 的 原始數(shù)據(jù)類型是 any ,在這里將它斷言為 number 類型
(age as number).toFixed(0);
(<number>age).toFixed(0);
// 將user斷言為非null和非undefined
user!.age
除非確切的知道變量的數(shù)據(jù)類型,否則不要使用類型斷言,這是因?yàn)轭愋蛿嘌詴?huì)讓 TypeScript 編譯器將變量當(dāng)做指定的類型,而不管它實(shí)際的類型,在程序運(yùn)行時(shí)可能有類型錯(cuò)誤。
類型守衛(wèi)
類型守衛(wèi)的工作是將數(shù)據(jù)類型收窄,比如,變量 age 的數(shù)據(jù)類型可能是 string 也可能是 number,現(xiàn)在要將 age 收窄為 string 類型,類型守衛(wèi)能實(shí)現(xiàn)它??傮w而言,有4種方式讓數(shù)據(jù)類型收窄。
使用 in 關(guān)鍵字
如果某變量的數(shù)據(jù)類型是聯(lián)合類型,并且該變量存在一個(gè)屬性絕對(duì)不會(huì)出現(xiàn)在聯(lián)合類型的其他成員類型上,那么可以使用 in 關(guān)鍵字將類型收窄。用法如下:
function printType(value: User | Student) {
// grade 只存在 Student 類型上
if ('grade' in value) {
// 在 if 塊中,value 的數(shù)據(jù)類型被收窄為 Student 類型
console.log('它是 Student 類型',value.name + ':' + value.grade)
} else {
// 在 else 塊中,value 的數(shù)據(jù)類型被收窄為 User 類型
console.log('它是 User 類型',value.name)
}
}
使用 instanceof 關(guān)鍵字
用 in 關(guān)鍵字收窄數(shù)據(jù)類型有局限性,必須有一個(gè)獨(dú)特的屬性作為判別符,否則,不能用 in 關(guān)鍵字收窄。如果正在處理的變量是類的實(shí)例,那么可以用 instanceof 關(guān)鍵字收窄數(shù)據(jù)類型。用法如下:
function printInfo(value: Staff | Student) {
if (value instanceof Staff) {
// 在 if 塊中,value 的數(shù)據(jù)類型被收窄為 Staff 類型
console.log('它是 Staff 類型')
} else {
// 在 else 塊中,value 的數(shù)據(jù)類型被收窄為 Student 類型
console.log('它是 Student 類型')
}
}
使用 typeof 關(guān)鍵字
使用 typeof 能得到值的數(shù)據(jù)類型,如果變量的類型為基本類型,如:string、number 等,使用 typeof 也能將數(shù)據(jù)類型收窄。用法如下:
function printType(value: string | number) {
if (typeof value === 'string') {
// value 的類型被收窄為 string
console.log('value 是 string 類型')
} else {
// value 的類型被收窄為 number
console.log('value 是 number 類型')
}
}
// 用對(duì)象上某個(gè)字段收窄數(shù)據(jù)類型
//如果 User 類型的 name 字段為 string 類型,Student 類型的 name 字段為 number 類型
function printObjType(obj: User | Student) {
if (typeof obj.name === 'string') {
// value 的類型被收窄為 User
} else {
// value 的類型被收窄為 Student
}
}
自定義類型守衛(wèi)
用 in、instanceof 和 typeof 關(guān)鍵字收窄數(shù)據(jù)類型語(yǔ)法很簡(jiǎn)單,但都有各自的局限性。如果它們不能當(dāng)作類型守衛(wèi),那么能使用 is 關(guān)鍵字自定義類型守衛(wèi),寫法為:parameter is Type,這種寫法被稱為類型謂詞,要將它放在函數(shù)返回值的位置。
類型謂詞所在的函數(shù)被稱為類型謂詞函數(shù),它的返回值必須為 boolean 類型。類型謂詞中的 Type可以是任意合法的 TypeScript 數(shù)據(jù)類型,parameter 可以是函數(shù)的參數(shù)也能是 this 關(guān)鍵字。
當(dāng)類型謂詞中的 parameter 是函數(shù)的參數(shù),用法如下:
function predicateStudent(value: Student | User): value is Student {
return typeof (value as any).garde === 'number'
}
function printObjType(obj: User | Student) {
if (predicateStudent(obj)) {
// obj的類型被收窄為 Student
} else {
// value 的類型被收窄為 User
}
}
上述代碼中的 predicateStudent 是類型謂詞函數(shù),如果它返回 true,那么參數(shù)的數(shù)據(jù)類型被收窄為 Student。
當(dāng)類型謂詞中的 parameter 是 this 關(guān)鍵字,這種用法通常出現(xiàn)在類的方法中,用法如下:
abstract class User {
name: string;
constructor(name: string) {
this.name = name;
}
isStudent(): this is Student {
return this instanceof Student;
}
isStaff(): this is Staff {
return this instanceof Staff;
}
}
class Student extends User{
grade: number;
constructor(name: string, grade: number) {
super(name)
this.grade = grade
}
}
class Staff extends User {
salary: number;
constructor(name: string, salary: number) {
super(name)
this.salary = salary
}
}
function printObjType(obj: User) {
if (obj.isStaff()) {
// obj 的類型被收窄為 Staff
} else if (obj.isStudent()){
// obj 的類型被收窄為 Student
}
}
上述代碼中的 User 是抽象類,不能被實(shí)例化,Staff 和 Student 都繼承自 User。實(shí)例方法 isStaff 用于將類型收窄為 Staff,實(shí)例方法 isStudent 用于將類型收窄為 Student。
總結(jié)
在項(xiàng)目中,如果某變量有多種數(shù)據(jù)類型,不建議使用類型斷言將它斷言成特定的類型,而是使用類型守衛(wèi)根據(jù)實(shí)際情況將類型收窄,然后按不同的類型分別處理。類型守衛(wèi)能讓應(yīng)用程序的數(shù)據(jù)類型更安全,不至于程序在編譯階段不報(bào)錯(cuò),但在運(yùn)行階段報(bào)錯(cuò)。
以上就是TypeScript類型斷言VS類型守衛(wèi)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于TypeScript類型斷言類型守衛(wèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
document.documentElement和document.body區(qū)別介紹
body是DOM對(duì)象里的body子節(jié)點(diǎn),即body標(biāo)簽,documentElement 是整個(gè)節(jié)點(diǎn)樹(shù)的根節(jié)點(diǎn)root,詳細(xì)介紹請(qǐng)看本文,感興趣的朋友可以參考下2013-09-09
Knockoutjs 學(xué)習(xí)系列(一)ko初體驗(yàn)
本篇主要簡(jiǎn)單介紹了knockoutjs中最重要的概念:可觀察對(duì)象(數(shù)組)。非常不錯(cuò)具有參考借鑒價(jià)值,感興趣的朋友快來(lái)圍觀吧2016-06-06
JS動(dòng)態(tài)添加與刪除select中的Option對(duì)象(示例代碼)
本篇文章主要介紹了JS動(dòng)態(tài)添加與刪除select中的Option對(duì)象(示例代碼) 需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-12-12
JavaScript進(jìn)階教程之非extends的組合繼承詳解
組合繼承有時(shí)候也叫偽經(jīng)典繼承,指的是將原型鏈和借用構(gòu)造函數(shù)技術(shù)組合到一塊,從而發(fā)揮二者之長(zhǎng)的一種繼承模式,下面這篇文章主要給大家介紹了關(guān)于JavaScript進(jìn)階教程之非extends的組合繼承的相關(guān)資料,需要的朋友可以參考下2022-08-08
深入理解JavaScript中為什么string可以擁有方法
下面小編就為大家?guī)?lái)一篇深入理解JavaScript中為什么string可以擁有方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05
JavaScript實(shí)現(xiàn)仿新浪微博大廳和騰訊微博首頁(yè)滾動(dòng)特效源碼
最近看到朋友用JavaScript實(shí)現(xiàn)仿新浪微博大廳和未登錄騰訊微博首頁(yè)滾動(dòng)效果,朋友使用jquery實(shí)現(xiàn)的,在網(wǎng)上看到有用js制作的也比較好,于是把我的內(nèi)容整理分享給大家,具體詳解請(qǐng)看本文2015-09-09
JavaScript字符串轉(zhuǎn)換數(shù)字的方法
這篇文章主要介紹了JavaScript字符串轉(zhuǎn)換數(shù)字的方法,文章圍繞JavaScript字符串轉(zhuǎn)換數(shù)字的相關(guān)資料展開(kāi)全文內(nèi)容,需要的小伙伴可以參考一下2021-12-12

