本文 AI 產出,尚未審核

TypeScript 陣列型別宣告:string[] vs Array<string>


簡介

在 TypeScript 中,陣列(Array)是最常用的集合型別,幾乎每個專案都會與之打交道。正確且一致的型別宣告不只是提升程式碼可讀性,更能讓編譯器在開發階段即捕捉到潛在的錯誤。
本單元聚焦於兩種等價的寫法——string[]Array<string>——說明它們的語法差異、使用情境與最佳實踐,幫助你在日常開發中做出最合適的選擇。


核心概念

1. 基本語法比較

寫法 語法說明
string[] 使用後置[] 來表示「此型別的陣列」
Array<string> 使用泛型 Array<T>,將元素型別作為參數傳入

兩者在編譯結果上完全等價,TypeScript 會把它們都映射成 Array<string>。差別僅在於 可讀性與其他泛型結構的統一性

// 兩種寫法皆可
let a: string[] = ["apple", "banana"];
let b: Array<string> = ["cat", "dog"];

小技巧:若你已經在使用其他泛型(例如 Promise<T>Map<K, V>),使用 Array<T> 能讓整段程式碼的風格更一致。


2. 多維陣列的寫法

多維陣列在 [] 與泛型寫法上會產生明顯差異,這也是選擇其中一種寫法的關鍵時機。

// 使用 [] 寫法
let matrix1: number[][] = [
  [1, 2],
  [3, 4],
];

// 使用泛型寫法
let matrix2: Array<Array<number>> = [
  [5, 6],
  [7, 8],
];
  • number[][] 看起來較為簡潔,但在深層嵌套時容易產生視覺混亂。
  • Array<Array<number>> 雖然較長,但在閱讀時可以清楚辨識每一層的「陣列」概念,對於 高階型別(如 Array<Array<Array<string>>>)更具可讀性。

3. 與其他泛型結構的協同

當你同時使用 MapSetPromise 等泛型時,保持同一風格會讓程式碼更一致。

type User = { id: number; name: string };

// 使用 [] 風格
let userNames: string[] = [];
let userMap: Map<number, User> = new Map();

// 使用泛型風格
let userNames2: Array<string> = [];
let userMap2: Map<number, User> = new Map();

建議:在大型專案中,若團隊已決定以「泛型」為主(Array<T>Promise<T>),就盡量遵守此規範;若偏好簡潔的 [],則全專案統一使用 []


4. 型別推斷與 readonly 陣列

TypeScript 能根據初始值自動推斷陣列型別,這時兩種寫法的差別仍然不大。但在 只讀(readonly) 陣列上,語法稍有不同:

// 使用 [] + readonly
const readonlyNames: readonly string[] = ["Alice", "Bob"];

// 使用泛型 + ReadonlyArray
const readonlyNames2: ReadonlyArray<string> = ["Charlie", "Dave"];

readonly 前綴只能與 [] 搭配,而 ReadonlyArray<T> 則是 內建泛型別名。若你需要 只讀 陣列,建議直接使用 ReadonlyArray<T>,這樣可以與 Array<T> 保持同一風格。


5. 範例彙總(5 個實用範例)

範例 1:基本宣告與迭代

// string[] 版
let fruits: string[] = ["apple", "orange", "pear"];
fruits.forEach(f => console.log(`水果: ${f}`));

// Array<string> 版
let vegetables: Array<string> = ["carrot", "broccoli"];
vegetables.map(v => v.toUpperCase()).forEach(v => console.log(`蔬菜: ${v}`));

範例 2:函式參數與回傳值

// 接收 string[] 的函式
function joinWords(words: string[]): string {
  return words.join(" ");
}

// 接收 Array<string> 的函式
function filterLongWords(words: Array<string>, minLen: number): Array<string> {
  return words.filter(w => w.length >= minLen);
}

範例 3:多維陣列與型別別名

type Matrix = number[][];               // 使用 [] 風格
type Matrix2 = Array<Array<number>>;    // 使用泛型風格

let m1: Matrix = [[1, 2], [3, 4]];
let m2: Matrix2 = [[5, 6], [7, 8]];

範例 4:只讀陣列

// 只讀陣列 (readonly + [])
const colors: readonly string[] = ["red", "green", "blue"];

// 只讀陣列 (ReadonlyArray)
const colors2: ReadonlyArray<string> = ["cyan", "magenta", "yellow"];

範例 5:與其他泛型結合

type ApiResponse<T> = Promise<Array<T>>;

// 取得字串陣列的 API
async function fetchUsernames(): ApiResponse<string> {
  const data = await fetch("/api/users").then(r => r.json());
  return data.names; // 假設回傳 { names: string[] }
}

常見陷阱與最佳實踐

陷阱 說明 解決方式
混用兩種寫法 在同一檔案或同一介面中同時使用 string[]Array<string>,會讓閱讀者感到混亂。 統一風格:在專案的 lint 規則(如 ESLint @typescript-eslint/array-type)中設定 defaultarraygeneric
錯把泛型當作函式 Array<string>() 會被誤認為是呼叫 Array 建構子,實際上會產生 空陣列,而非型別宣告。 僅用於型別位置Array<string> 只能寫在型別註解或泛型參數,不能直接作為值使用。
只讀與可變混用 readonly string[]Array<string> 同時出現在同一資料結構,可能導致意外的變更。 使用 ReadonlyArray<T> 或在介面中明確標註 readonly,保持一致性。
多維陣列的可讀性 string[][][] 會讓人難以辨識層級。 改用 Array<Array<Array<string>>>,或建立型別別名 type TripleStringArray = Array<Array<Array<string>>>;

推薦的 ESLint 設定

{
  "rules": {
    "@typescript-eslint/array-type": [
      "error",
      {
        "default": "array",          // 使用 string[]
        "readonly": "generic"       // 只讀陣列使用 ReadonlyArray<T>
      }
    ]
  }
}

小提醒:若團隊偏好 Array<T>,只要把 "default": "generic" 即可。


實際應用場景

  1. API 回傳資料
    多數 REST API 會回傳 JSON 陣列,例如 string[]。在型別定義上,使用 Array<string> 可以直接與其他泛型(如 Promise<T>)結合,寫出 Promise<Array<string>>,保持語法一致。

  2. React/Angular 狀態管理
    當使用 useState<string[]>([])this.items: Array<Item> = [] 時,兩者皆可。若你在同一個 component 中同時使用 Map<string, number>Set<number>,建議統一採用 泛型寫法,讓程式碼風格更整齊。

  3. 函式庫設計
    若你在發佈 npm 套件,對外介面最好使用 Array<T>,因為它更能與其他泛型類型(如 Observable<T>)自然結合,使用者在閱讀文件時也較不會混淆。

  4. 多維資料結構(表格、棋盤)
    在處理 2D/3D 表格或棋盤時,Array<Array<number>> 的寫法比 number[][] 更直觀,尤其當你需要把「陣列」這個概念抽象化成型別別名時。


總結

  • string[]Array<string> 功能等價,差別僅在語法表達與團隊風格。
  • 多維陣列、只讀陣列以及與其他泛型結合時,泛型寫法 (Array<T>) 更具可讀性與一致性
  • 為避免混亂,建議在 專案層面設定統一的 ESLint 規則,讓所有開發者遵守同一風格。
  • 在實務上,根據 API 回傳、框架狀態管理或函式庫設計 的需求選擇最合適的寫法,才能在 TypeScript 中發揮型別系統的最大效益。

掌握這兩種陣列型別的差異與最佳實踐,你就能寫出 更安全、更易讀、且維護成本低 的 TypeScript 程式碼。祝開發順利!