typescript類型保護


當遇到需要告訴編譯器某個值是指定類型的場景時,我們可以使用類型斷言,比如這個例子:

const valueList = [123, "hello"]

// getValue 函數隨機返回數字類型或者字符串類型
function getValue() {
    const num = Math.random() * 10
    if (num < 5) {
        return valueList[0]
    } else {
        return valueList[1]
    }
}

const v = getValue()
if (v.length) { // error,類型“string | number”上不存在屬性“length”。類型“number”上不存在屬性“length”。
    console.log(v.length)
} else {
    console.log(v.toFixed()) // 類型“string | number”上不存在屬性“toFixed”。類型“string”上不存在屬性“toFixed”。
}

這種情況在編譯階段報錯,可以使用類型斷言解決:

if ((v as string).length) {
    console.log((v as string).length)
} else {
    console.log((v as number).toFixed()) 
}

使用類型斷言雖然可以解決這種需要指定類型的情況,但是顯得有些繁瑣,我們嘗試類型保護的方式來優化。

 

自定義類型保護

類型保護就是一些表達式,它們會在運行時檢查以確保在某個作用域里的類型。 要定義一個類型保護,我們只要簡單地定義一個函數,它的返回值是一個 “類型謂詞”。比如可以這樣定義一個類型保護函數:

function isString(value: number | string): value is string{
    const num = Math.random() * 10
    return num > 5
}

例子中的 value is string 就是類型謂詞,value 必須是參數中的一個。使用它也很方便:

const v = getValue()
if (isString(v)) { 
    console.log(v.length)
} else {
    console.log(v.toFixed())
}

可以看到這比類型斷言更簡潔,只要檢查過一次類型,后續分支就不用檢查了,並且會自動推斷出 else 分支中的 v 是 number 類型。

 

typeof 類型保護

自定義類型保護需要定義一個函數來判斷類型,難免還是有些復雜,其實在 ts 中,如果是基本類型而不是復雜類型,可以直接使用 typeof 來做類型保護,如:

if (typeof v === 'string') { 
    console.log(v.length)
} else {
    console.log(v.toFixed())
}

這樣寫是可以的,效果和自定義類型保護一樣的。但它有一些限制,這些 typeof 類型保護只有兩種形式能被識別: typeof v === "typename"和 typeof v !== "typename", "typename"必須是 "number", "string", "boolean"或 "symbol"。 但是TypeScript並不會阻止你與其它字符串比較,語言不會把那些表達式識別為類型保護。

 

instanceof 類型保護

instanceof 操作符是 JS 中的原生操作符,用來判斷一個實例是不是某個構造函數創建的,或者是不是使用 es6 語法的某個類創建的。在 ts 中,使用 instanceof 操作符可以達到類型保護的效果。例子:

class Class1 {
    constructor(public name: string = 'aa') { }
}

class Class2 {
    constructor(public age: number = 18) { }
}

function getRandomItem() {
    return Math.random() > 0.5 ? new Class1() : new Class2()
}

const item = getRandomItem()
if (item instanceof Class1) {
    console.log(item.name)
} else {
    console.log(item.age)
}

if 分支中使用 instanceof 判斷了 item,如果是 Class1 創建的,那么應該有 name 屬性,如果不是,那它就有 age 屬性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM