網站搜尋

TypeScript 對 {} 使用什麼類型名稱?


TypeScript 使用什麼類型名稱來表示形式為 "{}" 的變數?

這對大多數人來說可能非常顯而易見,但我剛接觸 Typescript,正在轉換一些 Javascript,而這個基本問題居然很難在 Google 上找到答案。其他所有基本類型都有很好的文檔,但我找不到關於基本 hash 類型的資料。我不確定它是 `object`、`Object`、`Map` 還是 `any`。

答案#1

在所有實際情況下*,空物件類型({})可以與 Object 類型互換。所有具有屬性的值(即不是 null 或 undefined)都可以賦值給 Object 或 {}。

另一方面,object 類型是用於所有非原始值,因此它不能與 Object 或 {} 互換。

Map<KeyType, ValueType> 類型特別表示一個 Map 物件。

最後,any 字面意思是指 任何 值:它可以是原始值也可以不是,null 或 undefined,以及我在這裡未列出的任何東西。

查看更多 TypeScript 中 'object'、{} 和 Object 之間的差異。

即使它們在 TypeScript 中存在,你很可能並不真的想在你的程式碼中使用 {} 或 Object,有一個專門針對 TypeScript 的 eslint 規則可以提供更多細節:

當你輸入一個值為 {} 時,它會警告你:不要將 {} 用作類型。{} 實際上表示「任何非 null 或 undefined 的值」。

  • 如果你想要一種類型表示「任何物件」,你可能會想要使用 Record<string, unknown>。
  • 如果你想要一種類型表示「任何值」,你可能想要使用 unknown。
  • 如果你想要一種類型表示「空物件」,你可能想要使用 Record<string, never>。

在使用 Object 時:不要將 Object 作為類型使用。Object 類型實際上意味著「任何非 null 或 undefined 的值」,所以它比 unknown 略好一些。

  • 如果你想要一種類型表示「任何物件」,你可能會想要使用 Record<string, unknown>。
  • 如果你想要一種類型表示「任何值」,你可能想要使用 unknown。

* 空物件類型和 Object 類型在編譯時語義上實際上是不同的:內建方法(例如 .toString())對 {} 不進行類型檢查,但對 Object 則會進行檢查

答案#2

{} 是一個物件字面值。TypeScript 中的物件字面值幾乎可以定義任何類型的物件。像你的範例中那樣的 空 物件字面值(字面上為 {})等同於類型 Object。但是,如果物件字面值中有屬性,它會定義一個可能是匿名的類型,用來描述具有那些屬性的物件,而不僅僅是 Object 。(參見 Emma Koskinen 在其回答中連結的這個回答,以了解更多關於 {}、Object 和 object 的資訊。)

理解 TypeScript 型別系統的關鍵之一是它是 結構性(基於事物的形狀),而不是 名目性(基於事物的名稱)。例如:

interface Example {
    a: number;
    b: string;
}
function fn(x: Example) {
    console.log(x.a, x.b);
}

const obj = {a: 42, b: "Life, the Universe, and Everything"};
fn(obj); // <=== No error here

遊樂場連結

沒有任何東西表示 obj 是 Example 類型,但這沒關係,因為它與 Example 的賦值是相容的,所以將它傳遞給 fn 完全沒問題。

事實上,我們可以更進一步,明確地說 obj 是另一種型別:

interface Example {
    a: number;
    b: string;
}
function fn(x: Example) {
    console.log(x.a, x.b);
}

interface AnotherExample {
    a: number;
    b: string;
    c: boolean;
}

const obj: AnotherExample = {a: 42, b: "Life, the Universe, and Everything", c: true};
fn(obj); // <=== No error here

遊樂場連結

那裡,我們已經明確地說明了obj的類型是AnotherExample,這與Example(稍微)不同。但將它傳遞給fn仍然完全沒問題,因為fn所需要的只是該物件具有Example的結構(a: number; b: string;),而obj確實如此。它有一個額外的屬性c,但這對fn沒有影響。fn已經說過它只在乎a和b。