供 JavaScript 程式設計師使用的 TypeScript

TypeScript 與 JavaScript 的關係非比尋常。TypeScript 提供 JavaScript 的所有功能,並在這些功能之上增加了一層:TypeScript 的類型系統。

例如,JavaScript 提供了像 stringnumber 這樣的語言原語,但它不會檢查您是否已一致地指派這些。TypeScript 會執行檢查。

這表示您現有的運作 JavaScript 程式碼也是 TypeScript 程式碼。TypeScript 的主要好處是它可以強調您的程式碼中意外的行為,降低錯誤發生的機率。

本教學課程簡要說明 TypeScript,重點在於其類型系統。

透過推論的類型

TypeScript 了解 JavaScript 語言,而且在許多情況下會為您產生類型。例如,在建立變數並將其指派給特定值時,TypeScript 會使用該值作為其類型。

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

透過了解 JavaScript 的運作方式,TypeScript 可以建立一個接受 JavaScript 程式碼但具有類型的類型系統。這提供了一個類型系統,而不需要在您的程式碼中加入額外的字元來明確表示類型。這就是 TypeScript 知道在上述範例中 helloWorldstring 的方式。

您可能在 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

然後,您可以宣告一個 JavaScript 物件符合您的新 interface 的形狀,方法是在變數宣告後使用類似 : TypeName 的語法

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

如果您提供了一個與您提供的介面不符的物件,TypeScript 會警告您

ts
interface User {
name: string;
id: number;
}
 
const user: User = {
username: "Hayes",
Type '{ username: string; id: number; }' is not assignable to type 'User'. Object literal may only specify known properties, and 'username' does not exist in type 'User'.2322Type '{ username: string; id: number; }' is not assignable to type 'User'. Object 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 或沒有傳回值的函式)。

您會看到有兩種建立類型的語法:介面和類型。您應該偏好 interface。當您需要特定功能時,請使用 type

組合類型

使用 TypeScript,您可以透過組合簡單類型來建立複雜類型。有兩種常見的方式可以做到這一點:使用聯集和泛型。

聯集

使用聯集,您可以宣告一個類型可以是多個類型之一。例如,您可以將 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

聯集也提供了一種處理不同類型的方法。例如,您可能有一個函式需要一個 array 或一個 string

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"
function typeof f === "function"
array 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 的核心原則之一是,類型檢查專注於值的「形狀」。這有時稱為「鴨子類型」或「結構化類型」。

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

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)
DSDustin Stender (1)
MKMatt Kantor (1)
JCRJuan Carlos Ruiz (1)
IOIván Ovejero (1)
18+

最後更新:2024 年 3 月 21 日