TypeScript 2.0開啟空值的嚴格檢查

摘要:在編程過程成空指針是最常見的bug之一,但是在TypeScript中我們無法使用具體的類型來表示特定的變量不能為空!幸運的是,TypeScript 2.0 解決了這個問題。

本文分享自華為雲社區《TypeScript開啟嚴格空值檢查》,作者:搞前端的半夏。

在TS中,有對應JS中的基礎類型null和undefined。

TypeScript里,JS中的基本數據類型undefined和null兩者各自有自己的類型分別叫做undefined和null。

let u: undefined = undefined;
let n: null = null;

默認情況下null和undefined是所有類型的子類型。 就是說你可以把null和undefined賦值給number類型的變量。

例如下面的代碼,在TS中是完全可以執行的。

let userName: string;
userName = "搞前端的半夏";  // OK
userName = null;      // OK
userName = undefined; // OK

let age: number;
age = 18;        // OK
age = null;      // OK
age = undefined; // OK

let isBoy: boolean;
isBoy = true;      // OK
isBoy = false;     // OK
isBoy = null;      // OK
isBoy = undefined; // OK

在編程過程成空指針是最常見的bug之一,但是在TypeScript中我們無法使用具體的類型來表示特定的變量不能為空!幸運的是,TypeScript 2.0 解決了這個問題!。

strictNullChecks

TypeScript 2.0 增加了對不可為空類型的支持。有一種新的嚴格空值檢查模式,他提供了strictNullChecks

來限制對空值的檢查。可以通過在命令行上添加–strictNullChecks參數來啟功嚴格空值檢查。也可以在項目的tsconfig.json文件中啟用strictNullChecks編譯器選項。

在TS中,為了各版本的兼容,strictNullChecks的默認值是false

{
  "compilerOptions": {
    "strictNullChecks": true
    // ...
  }
}

在TS官方的演練場中你可以勾選strictNullChecks來啟用嚴格空值檢查!

注意點1

在嚴格空值檢查模式下,null和undefined無法賦值給其他類型的變量。

例如下面的代碼在*strictNullChecks=true下,是無法編譯通過的。

let userName: string;
userName = "搞前端的半夏";  // OK
userName = null;      // OK
userName = undefined; // OK

注意點2

嚴格空值檢查並不意味着變量的類型無法設置為null和undefined

例如下面的代碼在*strictNullChecks=true下,正常編譯通過的。

let userName: null;
userName = null;  

let age: undefined;
age = undefined;  

變量如何可以為空

在正常的編程中,我們並不會直接將一個變量的類型設置為null或者undefined,例如username,我們通常設置為string類型。

如果我們想要username可以接受空值我們該怎麼辦呢?

1. 使用聯合類型

聯合類型(Union Types)表示取值可以為多種類型中的一種。

對於下面的代碼,userName可以接受null類型的值。但是無法接受undefined的值

let userName: string | null;
userName = "搞前端的半夏";  // OK
userName = null;      // OK
userName = undefined; // Error

2. a? 默認undefined

聯合類型可以在Object中使用

type User = {
  name: string ;
  age:number | undefined
};

這裡我們設置age的類型為number和undefined。

下面的兩種用法都是正確的。

let user1: User = { name: "搞前端的半夏", age: undefined };
let user2: User = { name: "搞前端的半夏", age: 18 };

如果我們想要下面的效果,不需要手動給age賦值

let user2: User = { name: "搞前端的半夏"};

此時我們就需要用到**?**來使屬性成為可選,這樣我們就可以完全省略age屬性的定義。

type User = {
  name: string ;
  age?:number 
};

請注意,在這種情況下:undefined類型會自動添加到聯合類型中。因此,以下所有賦值都是正確的:

let user1: User = { name: "搞前端的半夏", age: undefined };
let user2: User = { name: "搞前端的半夏", age: 18 };
let user3: User = { name: "搞前端的半夏"};

安全檢查

變量可空的安全檢查

如果變量的類型包含nullor undefined,則訪問任何屬性都會產生編譯時錯誤:

function UserNameLength(userName: string | null) {
  return userName.length;
}

所以在訪問屬性之前,必須要先判斷變量的值是否為空!

function UserNameLength(userName: string | null) {
  if (userName === null) {
    return 0;
  }

  return userName.length;
}

#可空類型的函數調用

在JS中支持回調函數,所以函數的參數會可能是函數類型,

function fn(callback?: () => void) {
  callback();
}

如果該參數是可選的函數類型,TS會將該參數加上undefined類型。

那麼這個函數的我們在調用函數的時候會報錯!

類似於在訪問屬性之前檢查對象,我們需要首先檢查函數是否具有非空值:

function fn(callback?: () => void) {
  if (callback) {
    callback();
  }
}

 

點擊關注,第一時間了解華為雲新鮮技術~