Skip to main content

Command Palette

Search for a command to run...

TypeScript - 陣列的型別

Published
2 min readView as Markdown

在 TypeScript 中,可以使用多種方式來定義陣列的型別。

使用型別後綴法 Type Suffix Syntax:「型別 + 方括號」

在變數名稱後面加上 [],表示這個變數是一個陣列,裡面包含的元素都是同一個型別。

let numbers: number[] = [1, 2, 3, 4, 5]
let names: string[] = ['Anna', 'Bob', 'Cathy']

使用陣列泛型 Array Generic

我們也可以使用陣列泛型(Array Generic) Array<ElementType> 來表示陣列,其中 ElementType 是你想要的陣列元素型別。:

let numbers: Array<number> = [1, 2, 3, 4, 5]
let names: Array<string> = ['Anna', 'Bob', 'Cathy']

泛型(Generics)是指在定義函式、介面或類別的時候,不預先指定具體的型別,而在使用的時候再指定型別的一種特性。

泛型允許你在多個型別之間共享相同的結構,使得程式碼更具可複用性。

在這種表示法中,我們可以將其他型別放入尖括號 <> 中,例如基本型別、自定義型別或介面。

對陣列中的元素進行型別檢查

如果嘗試將不符合指定型別的值添加到陣列中,可以看到 TypeScript 會報錯:

let numbers: number[] = [1, 2, 3, 4, 5]
numbers.push('6')

// index.ts:2:14 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

使用介面表示陣列

interface NumberArray {
    [index: number]: number;
}
let numbers: NumberArray = [1, 2, 3, 4, 5]

在這個例子中,我們定義了一個 NumberArray 介面,它表示只要索引(index)的型別是 number 時,那麼值的型別就必須是 number

雖然介面也可以用來表示陣列,但通常我們會直接採用更簡單的「型別+括號」方式來表示陣列:

let numbers: number[] = [1, 2, 3, 4, 5]

那什麼時候才會用到介面來表示陣列呢?

當我們需要描述具有多個屬性和方法的複雜數據結構時,用介面來表示陣列反而會讓數據組織和結構更清晰易讀。

比方說,我們常用它來表示「類陣列物件」。

類陣列物件 Array-like Object

「類陣列物件」並不是陣列型別,而是指具有某些類似陣列特性的物件。它可以向陣列一樣使用索引存取元素,並且具有 length 屬性

類陣列物件:arguments

比如在 Javascript 中, arguments 是一個類陣列物件,因此不能使用一般的陣列方式來描述,需使用介面來描述:

// 使用型別+方括號表示 --> 報錯
function sum() {
    let args: number[] = arguments;
}

// Type 'IArguments' is missing the following properties from type 'number[]': pop, push, concat, join, and 24 more.
// 使用介面表示 --> 正確
function sum() {
    let args: {
        [index: number]: number;
        length: number;
        callee: Function;
    } = arguments;
}

內建介面 - IArguments

IArguments 是 TypeScript 的內建介面,已經定義好了型別,用於描述類陣列物件(Array-like Object),特別是用於描述 JavaScript 函數中的 arguments 類陣列物件。

它實際上就是:

interface IArguments {
    [index: number]: any;
    length: number;
    callee: Function;
    caller: Function;
}

IArguments 介面約束了:

  • 索引的型別是數字時,值的型別是 any

  • 需有lengthcalleecaller 屬性

其他常見的類陣列物件

除了 IArguments 之外其他常見的類陣列物件也有對應的介面:

1. NodeList

使用 document.querySelectorAll 或其他類似方法選取 DOM 元素時,會返回一個 NodeList 類陣列物件。它表示一組節點(Node)。

 const nodeList = document.querySelectorAll("div");

2. HTMLCollection

使用 document.getElementsByClassNamedocument.getElementsByTagName 等方法選取 DOM 元素時,會返回一個 HTMLCollection 類陣列物件。它表示一組 HTML 元素。

 const htmlCollection = document.getElementsByClassName("some-class");

類陣列物件都的共同特點

  • 具有數字索引

  • 具有 length 屬性

  • 可以像陣列一樣遍歷,但並非真正的陣列

任意型別 any 在陣列中的應用

常見的做法是用任意型別 any 來表示陣列中的元素可以是任何型別:

const mixedArray: any[] = [1, 'hello', true, { name: 'John' }, [3, 4, 5]]

// 可以加入任何型別的元素
mixedArray.push(18)
mixedArray.push('world')
mixedArray.push({ age: 30 })

混合型別的陣列

如果陣列中的元素有不同的型別,我們可以使用聯合型別(Union Types)來表示這種情況:

let mixedArray: (number | string)[] = [1, "two", 3, "four"];

Readonly 陣列

你可以使用 ReadonlyArray<ElementType> 來表示唯讀的陣列:

let readOnlyNumbers: ReadonlyArray<number> = [1, 2, 3];

在介面中使用陣列

你可以在介面中定義一個陣列的型別,然後在物件中使用該型別:

interface Data {
    values: number[];
    names: string[];
}

let data: Data = {
    values: [1, 2, 3],
    names: ["Alice", "Bob"]
};

Ref

More from this blog

TypeScript - 型別斷言(Type Assertion)

型別斷言是 TypScript 的一種機制,允許我們手動指定一個明確的型別,提供 TypeScript 編譯器無法自行推斷的額外型別資訊。 我們可以透過這兩種寫法來指定型別斷言: 語法 尖括號 <>(angle-bracket)語法 語法:<type>value - 在需要斷言的變數前加上 <Type> 即可 const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas") as 語法 語法:value as...

Oct 15, 20232 min read

JavaScript - Scope 作用域 & Closure 閉包

Scope 作用域 留言 什麼是作用域 「作用域就是一個變數的生存範圍,一旦出了這個範圍,就無法存取到這個變數」。 當我們把變數 a 宣告在 function 中,function 之外的地方都無法取用這個變數: // 把變數宣告在 function 中 function test1() { var a = "hello" } console.log(a) // Uncaught ReferenceError: a is not defined 但當我們把變數 b 宣告在全域,fu...

Oct 3, 20236 min read
JavaScript - Scope 作用域 & Closure 閉包

JavaScript - this 是誰、指向哪裡,以及 call、apply、bind

this 是什麼 this 是 JavaScript 的一個關鍵字 this 是 function 執行時,自動生成的一個內部物件 隨著 function 執行場合的不同,this 所指向的值,也會有所不同 this 與 function 在何處被宣告完全無關,而是取決於 function 被呼叫的方式 在大多數的情況下, this 代表的就是呼叫 function 的物件 (owner Object of the function) 當 function 是某個 object 的 ...

Oct 3, 20233 min read
JavaScript - this 是誰、指向哪裡,以及 call、apply、bind

JavaScript - Hoisting 提升

Hoisting 是怎麼發生的? 變數和函數的宣告會在編譯階段就被放入記憶體,但實際位置和程式碼中完全一樣。 從這段 MDN 對於 hoisting 的說明大概可以了解到,Javascript 在執行程式碼之前會先進行編譯,而在編譯的過程中會將變數宣告以及函式宣告提升 (hoist) 到該 scope 的頂端,但需注意這邊並非實際改動程式碼的位置。 JS 在運作時是分成「編譯」和「執行」兩個步驟。而 hoisting 是發生在編譯的階段。 JS 在編譯的階段會將變數及函式的宣告處理好(h...

Oct 3, 20233 min read
JavaScript - Hoisting 提升

Yachu's Dev Memo

18 posts