any
和 unknown
是兩個用於處理 型別不確定
的情況。雖然它們在某些情境下都可以用來處理不確定的值,但它們的用法和限制有所不同,我們一一來介紹:
在前面幾個章節,威爾豬應該或多或少都有提到盡量不要使用 任意型別 (any)
,因為它可以 儲存任何型別的值
,同時 取消了型別檢查
。這意味著在使用 any 型別時,TypeScript 將不會對該值進行任何型別的檢查,這樣就和寫 JavaScript 一樣了,還浪費時間寫 TypeScript 幹嘛呢?因此它在一些情況下確實很方便,但同時也可能導致運行時錯誤和型別安全性問題。我們看以下範例:
let anyValue: any = 3;
anyValue = "威爾豬"; // ⭕️ 正確
anyValue = true; // ⭕️ 正確
在上述範例中,我們宣告了一個 anyValue 變數,並將其設置為 any 型別
,將不同型別的值賦予給該變數,它完全不挑食都會吃下去,這也代表了失去使用 TypeScript 的意義。
未知型別 (unknown) 與 any 不同的是,unknown 保留了型別檢查
。這意味著在使用 unknown 型別時,我們需要在使用之前 進行型別檢查
或 進行類型斷言
,以確保安全的操作。看以下範例:
我們將 unknownValue 分別設置為 any 型別
和 unknown 型別
,看會發生什麼?
使用 any 型別:
使用 unknown 型別:
可以看到使用 any 型別輕鬆過關,而 unknown 型別會跳出警告,我們必須多做一些型別的判斷才能消除這問題。
let unknownValue: unknown = "Hello, TypeScript!";
// 需要進行型別檢查
if (typeof unknownValue === "string") {
console.log(unknownValue.toUpperCase()); // 輸出: HELLO, TYPESCRIPT!
}
由上面範例可知,unknown 型別
在使用之前需進行 typeof 型別檢查,確保只有當 unknownValue 是字串時才調用 toUpperCase 方法。
我們再看一個使用 斷言 的範例:
const handleValue = (unknownValue: unknown): void => {
// 強制斷言
console.log((unknownValue as string).toUpperCase());
};
handleValue("Hello, TypeScript!"); // 輸出: HELLO, TYPESCRIPT!
這個範例是我們強制將 unknown 型別轉成 string 型別,確保它可以使用字串的方法。
any | unknown | |
---|---|---|
方便性 | 超級方便 | 方便 |
使用場景 | 不知道型別,或為了暫時繞過型別檢查 | 不確定型別 |
型別檢查 | ❌ | ⭕️ |
安全性 | 低 | 較高 |
所以在開發 TypeScript 項目時,還是應該 優先考慮使用更具體的型別
,以確保程式碼的可讀性、可維護性和型別安全性。儘管 any 和 unknown 在某些情況下可能很好用,但我們應該謹慎使用,避免引入潛在的錯誤和不安全性。如果必須使用時 (真的不是偷懶),還是要 避免過度濫用 any 型別
,儘量選擇使用 unknown 型別來保留型別檢查,才不會執行後發現自己犯了低級失誤。