
- TypeScript 基礎
- TypeScript - 首頁
- TypeScript - 路線圖
- TypeScript - 概述
- TypeScript - 環境設定
- TypeScript - 基本語法
- TypeScript vs. JavaScript
- TypeScript - 特性
- TypeScript - 變數
- TypeScript - let & const
- TypeScript - 運算子
- TypeScript 基本型別
- TypeScript - 型別
- TypeScript - 型別註解
- TypeScript - 型別推斷
- TypeScript - 數字
- TypeScript - 字串
- TypeScript - 布林值
- TypeScript - 陣列
- TypeScript - 元組
- TypeScript - 列舉
- TypeScript - any
- TypeScript - never
- TypeScript - 聯合型別
- TypeScript - 字面量型別
- TypeScript - Symbol
- TypeScript - null vs. undefined
- TypeScript - 類型別名
- TypeScript 控制流
- TypeScript - 決策
- TypeScript - if 語句
- TypeScript - if else 語句
- TypeScript - 巢狀 if 語句
- TypeScript - switch 語句
- TypeScript - 迴圈
- TypeScript - for 迴圈
- TypeScript - while 迴圈
- TypeScript - do while 迴圈
- TypeScript 函式
- TypeScript - 函式
- TypeScript - 函式型別
- TypeScript - 可選引數
- TypeScript - 預設引數
- TypeScript - 匿名函式
- TypeScript - Function 建構函式
- TypeScript - rest 引數
- TypeScript - 引數解構
- TypeScript - 箭頭函式
- TypeScript 介面
- TypeScript - 介面
- TypeScript - 介面擴充套件
- TypeScript 類和物件
- TypeScript - 類
- TypeScript - 物件
- TypeScript - 訪問修飾符
- TypeScript - 只讀屬性
- TypeScript - 繼承
- TypeScript - 靜態方法和屬性
- TypeScript - 抽象類
- TypeScript - 存取器
- TypeScript - 鴨子型別
- TypeScript 高階型別
- TypeScript - 交叉型別
- TypeScript - 型別守衛
- TypeScript - 型別斷言
- TypeScript 型別操作
- TypeScript - 從型別建立型別
- TypeScript - keyof 型別運算子
- TypeScript - typeof 型別運算子
- TypeScript - 索引訪問型別
- TypeScript - 條件型別
- TypeScript - 對映型別
- TypeScript - 模板字面量型別
- TypeScript 泛型
- TypeScript - 泛型
- TypeScript - 泛型約束
- TypeScript - 泛型介面
- TypeScript - 泛型類
- TypeScript 其他
- TypeScript - 三斜槓指令
- TypeScript - 名稱空間
- TypeScript - 模組
- TypeScript - 環境宣告
- TypeScript - 裝飾器
- TypeScript - 型別相容性
- TypeScript - Date 物件
- TypeScript - 迭代器和生成器
- TypeScript - Mixin
- TypeScript - 實用程式型別
- TypeScript - 裝箱和拆箱
- TypeScript - tsconfig.json
- 從 JavaScript 到 TypeScript
- TypeScript 有用資源
- TypeScript - 快速指南
- TypeScript - 有用資源
- TypeScript - 討論
TypeScript - 型別相容性
在 TypeScript 中,型別相容性是指將一種型別的變數、物件等賦值給另一種型別的能力。換句話說,它指的是根據型別的結構檢查兩種型別是否相容的能力。
例如,字串和布林型別彼此不相容,如下面的程式碼所示。
let s:string = "Hello"; let b:boolean = true; s = b; // Error: Type 'boolean' is not assignable to type 'string' b = s; // Error: Type 'string' is not assignable to type 'boolean'
TypeScript 的型別系統允許執行編譯時不安全的某些操作。例如,任何型別的變數都與 'any' 型別相容,這是不安全的行為。
例如:
let s: any = 123; s = "Hello"; // Valid
TypeScript 如何執行型別相容性檢查?
Typescript 使用結構化子型別和結構化賦值來執行型別相容性檢查。讓我們透過示例學習每一個。
結構化子型別
TypeScript 使用結構化子型別方法來檢查特定型別是否為另一種型別的子型別。即使特定型別的成員名稱不匹配,但結構匹配,TypeScript 編譯器也會將這兩種型別視為相同。
例如:
interface Person { name: string; } let person: Person; let obj = { name: "John", age: 30 }; // Ok person = obj;
要檢查 'obj' 物件的型別是否與 Person 介面的型別相容,typescript 會檢查 'obj' 是否至少包含 Person 介面中包含的所有屬性和方法。
TypeScript 不關心新增到子型別的額外成員。這裡,obj 物件包含一個額外的 'age' 屬性,但它仍然與 Person 型別相容,因為 obj 物件包含字串型別的 'name' 屬性。
如果 'obj' 物件不包含 Person 介面的所有成員,則它不能賦值給具有 Person 型別的物件。例如:
interface Person { name: string; } let person: Person; let obj = { n: "John", age: 30 }; // Not Ok person = obj;
當我們編譯上述程式碼時,它會丟擲錯誤,因為 'obj' 物件的型別與 Person 介面不同。
如何有效地使用型別相容性?
開發人員可以使用介面和泛型來有效地在 TypeScript 中使用型別。以下是使用介面和泛型進行型別相容性的最佳技巧。
使用介面
使用介面,開發人員可以定義契約或型別,以確保實現符合這些型別。這有助於確保程式碼不同部分之間的型別相容性。
讓我們透過下面的示例來了解它。
示例
在下面的示例中,'user2' 變數的型別為 'User'。因此,開發人員可以將具有與 'User' 介面相同屬性的物件賦值給 'user2' 物件。
interface User { name: string; age: number; } const user = { name: "Alice", age: 30 }; let user2: User = user; console.log(user2)
編譯後,它將生成以下 JavaScript 程式碼。
const user = { name: "Alice", age: 30 }; let user2 = user; console.log(user2);
輸出
其輸出如下:
{ name: 'Alice', age: 30 }
使用泛型
我們可以使用泛型來建立可重用的元件,這些元件可以與多種資料型別一起工作,而不是單一資料型別。它允許開發人員將型別作為引數傳遞,並將其用於變數、物件、類、函式引數等。
讓我們透過下面的示例來了解它。
示例
在下面的程式碼中,我們有一個 'Wrapper' 介面,它將資料型別作為引數。我們建立了 stringWrapper 和 numberWrapper 變數,並將字串和數字資料型別作為引數傳遞。
// Define a generic interface with a single property interface Wrapper<T> { value: T; } // Use the interface with a string type let stringWrapper: Wrapper<string> = { value: "Hello, TypeScript!", }; // Use the interface with a number type let numberWrapper: Wrapper<number> = { value: 123, }; console.log(stringWrapper.value); // Output: Hello, TypeScript! console.log(numberWrapper.value); // Output: 123
編譯後,它將生成以下 JavaScript 程式碼。
// Use the interface with a string type let stringWrapper = { value: "Hello, TypeScript!", }; // Use the interface with a number type let numberWrapper = { value: 123, }; console.log(stringWrapper.value); // Output: Hello, TypeScript! console.log(numberWrapper.value); // Output: 123
輸出
上述示例程式碼將產生以下輸出:
Hello, TypeScript! 123
函式和型別相容性
當我們比較或將一個函式賦值給另一個函式時,TypeScript 編譯器會檢查目標函式是否至少具有與源函式相同的引數和返回型別。如果您將函式 'x' 賦值給函式 'y',則函式 'x' 是目標函式,函式 'y' 是源函式。函式 'y' 中的附加引數不會導致任何錯誤。
示例
在下面的程式碼中,函式 'x' 只包含 1 個引數,而函式 'y' 包含 2 個引數。當我們將函式 'x' 賦值給函式 'y' 時,附加引數 's' 不會導致任何錯誤。
// Defining functions let x = (a: number) => { console.log(a); }; let y = (b: number, s: string) => { console.log(b + s); }; y = x; // OK // x = y; // Error: x does not accept two arguments.
類和型別相容性
當我們比較兩個類時,它只比較例項的成員。類建構函式和靜態成員屬於類本身,因此它們不包含在比較中。
示例
在此程式碼中,變數 'a' 和變數 'b' 具有相同的例項成員。因此,當我們將變數 'a' 賦值給 'b' 時,它不會引發任何錯誤。
class Animal { feet: number; constructor(name: string, numFeet: number) {} } class Size { feet: number; constructor(meters: number) {} } let a: Animal; let s: Size; // Works because both classes have the same shape (they have the same instance properties). a = s;
您可以使用介面和泛型進行型別相容性。對於函式,目標函式應該至少具有與源函式相同的引數。對於類的型別相容性,它們應該具有相同的例項成員。