面向 JavaScript 開發者的 TypeScript

TypeScript 與 JavaScript 的關係不同尋常。TypeScript 提供了 JavaScript 的所有功能,並在其之上增加了一層:TypeScript 的型別系統。

例如,JavaScript 提供了諸如 stringnumber 這樣的語言原語,但它不會檢查你是否始終如一地分配了這些型別。而 TypeScript 會。

這意味著你現有的、可執行的 JavaScript 程式碼同樣也是 TypeScript 程式碼。TypeScript 的主要優勢在於它能夠突出顯示程式碼中意外的行為,從而降低出現 Bug 的機率。

本教程簡要概述了 TypeScript,重點介紹其型別系統。

型別推論

TypeScript 瞭解 JavaScript 語言,並在許多情況下為你生成型別。例如,在建立變數並將其賦值為特定值時,TypeScript 會使用該值作為其型別。

ts
let helloWorld = "Hello World";
let helloWorld: string
Try

透過理解 JavaScript 的工作方式,TypeScript 可以構建一個既接受 JavaScript 程式碼又具備型別的型別系統。這使得你無需新增額外的字元來顯式定義型別。這就是為什麼在上面的例子中,TypeScript 知道 helloWorld 是一個 string

你可能在 Visual Studio Code 中編寫過 JavaScript,並體驗過編輯器自動補全功能。Visual Studio Code 在底層使用 TypeScript 來使 JavaScript 開發變得更加輕鬆。

定義型別

你可以在 JavaScript 中使用多種設計模式。然而,有些設計模式使得型別很難自動推斷(例如使用動態程式設計的模式)。為了涵蓋這些情況,TypeScript 支援對 JavaScript 語言進行擴充套件,為你提供告知 TypeScript 型別應該是何種形式的位置。

例如,若要建立一個包含 name: stringid: number 的推斷型別物件,你可以這樣寫:

ts
const user = {
name: "Hayes",
id: 0,
};
Try

你可以使用 interface(介面)宣告顯式描述該物件的形狀:

ts
interface User {
name: string;
id: number;
}
Try

隨後,你可以在變數聲明後使用 : TypeName 語法,宣告一個 JavaScript 物件符合你新定義的 interface 的形狀。

ts
const user: User = {
name: "Hayes",
id: 0,
};
Try

如果你提供的物件與你指定的介面不匹配,TypeScript 會向你發出警告。

ts
interface User {
name: string;
id: number;
}
 
const user: User = {
username: "Hayes",
Object literal may only specify known properties, and 'username' does not exist in type 'User'.2353Object literal may only specify known properties, and 'username' does not exist in type 'User'.
id: 0,
};
Try

由於 JavaScript 支援類和麵向物件程式設計,TypeScript 也同樣支援。你可以將介面宣告與類一起使用。

ts
interface User {
name: string;
id: number;
}
 
class UserAccount {
name: string;
id: number;
 
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
}
 
const user: User = new UserAccount("Murphy", 1);
Try

你可以使用介面來註解函式的引數和返回值。

ts
function deleteUser(user: User) {
// ...
}
 
function getAdminUser(): User {
//...
}
Try

JavaScript 中已有一組可用的原始型別:booleanbigintnullnumberstringsymbolundefined,你可以在介面中使用它們。TypeScript 在此基礎上擴充套件了一些型別,例如 any(允許任何內容)、unknown(確保使用此型別的人宣告其確切型別)、never(此型別不可能發生)以及 void(返回 undefined 或沒有返回值的函式)。

你會發現構建型別有兩種語法:介面(Interfaces)和類型別名(Types)。你應該優先選擇 interface。當需要特定功能時,再使用 type

組合型別

使用 TypeScript,你可以透過組合簡單型別來建立複雜型別。有兩種常用的方法:聯合(Unions)和泛型(Generics)。

聯合型別

透過聯合,你可以宣告一個型別可以是多種型別之一。例如,你可以將 boolean 型別描述為 truefalse

ts
type MyBool = true | false;
Try

注意:如果你將滑鼠懸停在上面的 MyBool 上,會看到它被歸類為 boolean。這是結構化型別系統的一個特性。下面會詳細介紹。

聯合型別的一個流行用例是描述允許作為值的 stringnumber 字面量 集合。

ts
type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
type PositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
Try

聯合也提供了處理不同型別的方法。例如,你可能有一個接收 arraystring 的函式。

ts
function getLength(obj: string | string[]) {
return obj.length;
}
Try

要了解變數的型別,請使用 typeof

型別 謂詞
string typeof s === "string"
number typeof n === "number"
boolean typeof b === "boolean"
undefined typeof undefined === "undefined"
函式 typeof f === "function"
陣列 Array.isArray(a)

例如,你可以讓函式根據傳入的是字串還是陣列返回不同的值。

ts
function wrapInArray(obj: string | string[]) {
if (typeof obj === "string") {
return [obj];
(parameter) obj: string
}
return obj;
}
Try

泛型

泛型為型別提供了變數。一個常見的例子是陣列。沒有泛型的陣列可以包含任何東西。帶有泛型的陣列可以描述陣列中包含的值的型別。

ts
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;

你可以宣告使用泛型的自定義型別。

ts
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
 
// This line is a shortcut to tell TypeScript there is a
// constant called `backpack`, and to not worry about where it came from.
declare const backpack: Backpack<string>;
 
// object is a string, because we declared it above as the variable part of Backpack.
const object = backpack.get();
 
// Since the backpack variable is a string, you can't pass a number to the add function.
backpack.add(23);
Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.
Try

結構化型別系統

TypeScript 的核心原則之一是型別檢查關注的是值的形狀。這有時被稱為“鴨子型別(duck typing)”或“結構化型別(structural typing)”。

在結構化型別系統中,如果兩個物件具有相同的形狀,它們就被視為同一型別。

ts
interface Point {
x: number;
y: number;
}
 
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`);
}
 
// logs "12, 26"
const point = { x: 12, y: 26 };
logPoint(point);
Try

point 變數從未被宣告為 Point 型別。然而,TypeScript 在型別檢查時會比較 point 的形狀和 Point 的形狀。它們形狀相同,因此程式碼透過檢查。

形狀匹配僅要求物件的欄位子集匹配即可。

ts
const point3 = { x: 12, y: 26, z: 89 };
logPoint(point3); // logs "12, 26"
 
const rect = { x: 33, y: 3, width: 30, height: 80 };
logPoint(rect); // logs "33, 3"
 
const color = { hex: "#187ABF" };
logPoint(color);
Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, y2345Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, y
Try

類和物件符合形狀的方式沒有區別。

ts
class VirtualPoint {
x: number;
y: number;
 
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
 
const newVPoint = new VirtualPoint(13, 56);
logPoint(newVPoint); // logs "13, 56"
Try

如果物件或類具有所有必需的屬性,TypeScript 就會認為它們匹配,而不管具體的實現細節如何。

後續步驟

這是對日常 TypeScript 中使用的語法和工具的簡要概述。從這裡開始,您可以

TypeScript 文件是一個開源專案。歡迎提交 Pull Request 來幫助我們改進這些頁面 ❤

此頁面的貢獻者
OTOrta Therox (24)
JBJonathan Berger (1)
DSDustin Stender (1)
MKMatt Kantor (1)
JCRJuan Carlos Ruiz (1)
19+

最後更新:2026 年 3 月 27 日