有時候,我們可能需要在變數中儲存值。但在開發的時候並不確定它的型別。且未知值可能來自第三方 API 或使用者輸入的內容。在這種情況下,就可以選擇退出型別檢查並允許值通過編譯時檢查。
// 先行宣告型別
let response: any;
// 首先:賦值數字型別
response = 1;
console.log(response); // 1
// 再賦值為字串型別的內容
response = 'Hello world!';
console.log(response); // "Hello world!"
// 最後又改賦值為陣列型別
response = [1, 2, 3];
const sum = response.reduce((a: number, b: number) => a + b, 0);
console.log(sum); // 6
接下來看看,如果是在開發時不知道資料型別,TypeScript 會自動型別推論為 any
。
// 從 API 取得某一段 json
const json = `{"name": Annie, "age": 20}`;
// 轉換 json 印出結果
const userData = JSON.parse(json);
// 正確引用
console.log(userData); // {name: "Annie", age: 20}
// 錯誤引用
console.log(userData.favoriteColor) // undefined
你會發現,當試著取用 any
型別裡沒被宣告的元素資料時,並不會看到 TypeScript 的錯誤提示,而是印出了 undefined
。
簡單看過例子後,得出以下結論:
any
類型可以儲存任何型別的值,它讓編譯器跳過型別檢查。any
型別來儲存在編譯時或將 JavaScript 專案遷移到 TypeScript 專案時不知道其型別的值。unknown
和 any
型別有一點類似的地方,就是都可以指派任何變數值給它們。而 unknown
型別可以用來存放原本未知、但卻需要做型別檢查的值。
// 基本宣告
let response: unknown;
response = 1;
response = 'hello world!';
response = false;
response = { name: 'John' };
response = [1, 2, 3];
如果我們現在將 response
賦值為一組陣列資料,並試著呼叫它搭配陣列的方法做使用,則會發現 TypeScript 會發出錯誤警告(因為它的型別仍然是 unknown
):
這就是跟
any
型別不同的地方。
let response: unknown;
response = [1,2,3];
const sum = response.reduce((a: number, b:number ) => a + b, 0);
console.log(sum); // error
但可以選擇搭配型別斷言來告訴編譯器結果的型別是什麼:
let response: unknown;
response = [1, 2, 3];
const sum = (response as number[]).reduce((a: number, b: number) => a + b, 0);
console.log(sum); // 6
any
和 unknown
比較特徵 | any |
unknown |
---|---|---|
安全性 | 無 | 有 |
操作方式 | 無需檢查即可執行操作 | 沒有型別斷言就無法執行操作(縮小型別) |
安全性 | 對於動態值有用但不安全 | 對於動態值很有用且安全,因為它需要在使用前進行驗證。 |
檢查程度 | 不會對變數執行型別檢查 | 會對變數執行型別檢查 |
常見使用場景 | 用於將 JavaScript 程式碼庫遷移到 TypeScript。 | 在處理來自需要類型驗證的外部來源(API 呼叫、資料庫等)的資料時使用。 |