Wen Chen
Published on

「TS筆記」非空斷言操作符(!)

Authors
  • avatar
    Name
    Wen Chen

非空斷言操作符(Non-null Assertion Operator)

非空斷言操作符雖說長得跟我們熟悉的 ?. (optional chaining operator) 很像,但非空斷言操作符(!.) 是 TypeScript 專屬的語法。

就如同字面上的意思,! 讓開發者可以透過 ! ,強制告訴 compiler 這個變數的值不會是 null 或是 undefined,讓我們在操作變數的時候,不會出現可能是 null 的錯

Object is possibly 'null' or 'undefined'.

使用情境

我們先看一下底下的程式碼:

function greet( name: string | null = "Wen") {
  console.log(`Hello, ${name.toUpperCase()}!`);
}

上面的程式碼,雖然說我們在 name 給予了初始值,但還是會出現以下的錯誤:

'name' is possibly 'null'.

原因便在於,雖然我們有給予預設值,但他的型別還是有可能出現 null,所以假如我們可以確定不會有 nullundefined 的情況發生,我們可以將程式碼改成:

function greet( name: string | null = "Wen") {
  console.log(`Hello, ${name!.toUpperCase()}!`);
}

greet();      // "Hello, WEN!"

這樣便可以斷言 name 輸入值不會有 nullundefined 的情境,且因為有預設值,greet 也可以順利運作。

十分注意!

就使用上來說,非空斷言操作符在使用上,其實有點像 ignore 的感覺,斷言這個值不會有 nullundefined,但如我們在沒有確定的情況下,編譯時發現該值是 nullundefined 的話還是會爆掉的,所以還是要謹慎使用。

function greet( name?: string | null ) {
  console.log(`Hello, ${name!.toUpperCase()}!`);
}

greet();

// [ERR]: "Executed JavaScript Failed:"
// [ERR]: Cannot read properties of undefined (reading 'toUpperCase')

這麼危險,為什麼還需要他 ?

看到這裡,可能很多人會想:

聽起來很可怕,那為什麼不好好寫 Code 就好?

實際上,很多時候我們會用一些現成的函數,或是用某些從套件取出的變數,有時候我們明知道該變數不可能為空值,但現實就是那現成的函數/元件我們改不了,! 便是提供我們用更方便的告訴 TS 這東西肯定不會為空值。

當然我們也可以透過 if 判斷變數為空值才執行,這樣也可以達到一樣效果,但用 ! 可以少寫很多程式碼,在這時候就很方便了。

就如同前面提到的,當我們加上 !,就等同於告訴 TS :「 現在由我來檢查型別,我說有那他就有!」,而這也意味著我們要為自己的行為負責,假設我們再加上 ! 之後導致 Null Pointer Exception ,那就不是 TS 的問題了。