- 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 - Mixins
- TypeScript - 實用工具型別
- TypeScript - 裝箱和拆箱
- TypeScript - tsconfig.json
- 從 JavaScript 到 TypeScript
- TypeScript 有用資源
- TypeScript - 快速指南
- TypeScript - 有用資源
- TypeScript - 討論
TypeScript - 鴨子型別
鴨子型別
物件的型別由其行為(例如方法和屬性)而不是其類來決定的情況稱為“鴨子型別”。
TypeScript 中介面的使用使得鴨子型別成為可能。其中介面描述了物件必須具有的方法和屬性集才能屬於該型別。
例如,如果一個介面定義了函式,那麼任何具有名為“myFunc()”的方法的物件都可以被視為屬於特定型別,而不管其類是什麼。
鴨子型別強調透過考慮物件的方法和屬性來評估物件是否適合特定任務,而不是考慮其實際型別。介面說明了物件必須具有的屬性和方法集,才能被認為是特定目的的“鴨子型別”。
鴨子型別的益處
鴨子型別的主要優勢之一是使程式碼更加靈活和可重用。程式碼可以與任何具有所需方法和屬性的物件一起工作,而不僅僅是特定型別的物件,並且可以在各種情況下使用而無需修改。鴨子型別還透過允許在單個程式碼庫中互換使用不同型別的物件來提高程式碼重用性。
TypeScript 中鴨子型別的示例
以下是如何在 TypeScript 中使用鴨子型別的示例:
定義一個介面來表示您希望物件具有的行為。例如:
interface Duck {
quack(): void;
}
建立一個實現該介面的類。例如:
class MallardDuck implements Duck {
quack(): void {
console.log("Quack!");
}
}
建立該類的例項並將其用作介面定義的型別。
let duck: Duck = new MallardDuck(); duck.quack(); // Output: "Quack!"
建立另一個也實現該介面的類:
class RubberDuck implements Duck {
quack(): void {
console.log("Squeak!");
}
}
將新的類例項用作介面定義的相同型別。
let duck: Duck = new RubberDuck(); duck.quack(); // Output: "Squeak!"
正如您所看到的,MallardDuck 和 RubberDuck 類都實現了 Duck 介面,並且 duck 變數可以賦值給這兩個類的例項。型別由介面中定義的行為(方法和屬性)決定,而不是由類決定。
還需要注意的是,在 TypeScript 中,您可以使用 typeof 關鍵字在執行時檢查物件的型別,以及物件是否具有預期的方法或屬性。
示例
在這個例子中,Bird 和 Plane 類實現了 Flyable 介面,該介面需要一個 fly() 方法。這兩個“鴨子型別”可以在 goFly() 函式中互換使用。該函式不關心傳遞給它的物件的實際型別,只要它有一個可以呼叫的 fly() 方法即可。
interface Flyable {
fly(): void;
}
class Bird implements Flyable {
fly(): void {
console.log("Bird is flying");
}
}
class Plane implements Flyable {
fly(): void {
console.log("Plane is flying");
}
}
function goFly(flyable: Flyable) {
flyable.fly();
}
let bird = new Bird();
let plane = new Plane();
goFly(bird); // Prints "Bird is flying"
goFly(plane); // Prints "Plane is flying"
編譯後,它將生成以下 JavaScript 程式碼:
var Bird = /** @class */ (function () {
function Bird() {
}
Bird.prototype.fly = function () {
console.log("Bird is flying");
};
return Bird;
}());
var Plane = /** @class */ (function () {
function Plane() {
}
Plane.prototype.fly = function () {
console.log("Plane is flying");
};
return Plane;
}());
function goFly(flyable) {
flyable.fly();
}
var bird = new Bird();
var plane = new Plane();
goFly(bird); // Prints "Bird is flying"
goFly(plane); // Prints "Plane is flying"
輸出
上述程式碼將產生以下輸出:
Bird is flying Plane is flying
示例
總的來說,鴨子型別是一個強大的程式設計概念,它允許在 TypeScript 程式碼中實現更大的靈活性和可重用性,因為只要物件具有相同的方法和屬性,就可以互換使用不同型別的物件。在這個例子中,Driveable 介面、Car 和 Truck 類展示了相同的情況。
interface Driveable {
drive(): void;
}
class Car implements Driveable {
drive(): void {
console.log("Car is driving");
}
}
class Truck implements Driveable {
drive(): void {
console.log("Truck is driving");
}
}
function goDrive(driveable: Driveable) {
driveable.drive();
}
let car = new Car();
let truck = new Truck();
goDrive(car); // Prints "Car is driving"
goDrive(truck); // Prints "Truck is driving"
編譯後,它將生成以下 JavaScript 程式碼:
var Car = /** @class */ (function () {
function Car() {
}
Car.prototype.drive = function () {
console.log("Car is driving");
};
return Car;
}());
var Truck = /** @class */ (function () {
function Truck() {
}
Truck.prototype.drive = function () {
console.log("Truck is driving");
};
return Truck;
}());
function goDrive(driveable) {
driveable.drive();
}
var car = new Car();
var truck = new Truck();
goDrive(car); // Prints "Car is driving"
goDrive(truck); // Prints "Truck is driving"
輸出
上述程式碼將產生以下輸出:
Car is driving Truck is driving
鴨子型別背後的主要思想是,程式碼應該編寫成與任何具有所需方法和屬性的物件一起工作,而不是編寫成與特定物件一起工作。這可以使程式碼更靈活、更可重用,允許您互換使用不同型別的物件而無需更改程式碼。