
- TypeScript Basics
- TypeScript - Home
- TypeScript - Roadmap
- TypeScript - Overview
- TypeScript - Environment Setup
- TypeScript - Basic Syntax
- TypeScript vs. JavaScript
- TypeScript - Features
- TypeScript - Variables
- TypeScript - let & const
- TypeScript - Operators
- TypeScript Basic Types
- TypeScript - Types
- TypeScript - Type Annotations
- TypeScript - Type Inference
- TypeScript - Numbers
- TypeScript - Strings
- TypeScript - Boolean
- TypeScript - Arrays
- TypeScript - Tuples
- TypeScript - Enums
- TypeScript - Any
- TypeScript - Never
- TypeScript - Union
- TypeScript - Literal Types
- TypeScript - Symbols
- TypeScript - null vs. undefined
- TypeScript - Type Aliases
- TypeScript Control Flow
- TypeScript - Decision Making
- TypeScript - If Statement
- TypeScript - If Else Statement
- TypeScript - Nested If Statements
- TypeScript - Switch Statement
- TypeScript - Loops
- TypeScript - For Loop
- TypeScript - While Loop
- TypeScript - Do While Loop
- TypeScript Functions
- TypeScript - Functions
- TypeScript - Function Types
- TypeScript - Optional Parameters
- TypeScript - Default Parameters
- TypeScript - Anonymous Functions
- TypeScript - Function Constructor
- TypeScript - Rest Parameter
- TypeScript - Parameter Destructuring
- TypeScript - Arrow Functions
- TypeScript Interfaces
- TypeScript - Interfaces
- TypeScript - Extending Interfaces
- TypeScript Classes and Objects
- TypeScript - Classes
- TypeScript - Objects
- TypeScript - Access Modifiers
- TypeScript - Readonly Properties
- TypeScript - Inheritance
- TypeScript - Static Methods and Properties
- TypeScript - Abstract Classes
- TypeScript - Accessors
- TypeScript - Duck-Typing
- TypeScript Advanced Types
- TypeScript - Intersection Types
- TypeScript - Type Guards
- TypeScript - Type Assertions
- TypeScript Type Manipulation
- TypeScript - Creating Types from Types
- TypeScript - Keyof Type Operator
- TypeScript - Typeof Type Operator
- TypeScript - Indexed Access Types
- TypeScript - Conditional Types
- TypeScript - Mapped Types
- TypeScript - Template Literal Types
- TypeScript Generics
- TypeScript - Generics
- TypeScript - Generic Constraints
- TypeScript - Generic Interfaces
- TypeScript - Generic Classes
- TypeScript Miscellaneous
- TypeScript - Triple-Slash Directives
- TypeScript - Namespaces
- TypeScript - Modules
- TypeScript - Ambients
- TypeScript - Decorators
- TypeScript - Type Compatibility
- TypeScript - Date Object
- TypeScript - Iterators and Generators
- TypeScript - Mixins
- TypeScript - Utility Types
- TypeScript - Boxing and Unboxing
- TypeScript - tsconfig.json
- From JavaScript To TypeScript
- TypeScript Useful Resources
- TypeScript - Quick Guide
- TypeScript - Cheatsheet
- TypeScript - Useful Resources
- TypeScript - Discussion
TypeScript - Duck Typing
Duck Typing
The circumstance where an object's type is decided by its behavior, like methods and attributes, rather than its class is known as "duck typing".
The usage of interfaces in TypeScript makes duck typing possible. Where interface means the set of methods and characteristics an object must have to fall under that type are described.
For example, if an interface defines the function, any object with the method called "myFunc()" may be treated as belonging to a specific kind, regardless of its class.
Duck typing emphasizes assessing an object's suitability for a task by considering its methods and attributes instead of its actual type. An interface explains the set of properties and methods an object must have to be considered "duck typed" for a particular purpose.
Benefits of Duck Typing
One of duck typing's main benefits is making code more flexible and reusable. The code works with any object with the required methods and properties rather than just particular types of objects and may be used in various situations without requiring modification. Duck typing also improves code reuse by enabling the interchangeable usage of objects of diverse kinds within a single codebase.
Exmaples of Duck Typing is TypeScript
Here is an example of how to use duck typing in TypeScript
Define an interface that represents the behaviour you want an object to have. For example
interface Duck { quack(): void; }
Create a class that implements the interface. For example
class MallardDuck implements Duck { quack(): void { console.log("Quack!"); } }
Create an instance of the class and use it as the type defined by the interface.
let duck: Duck = new MallardDuck(); duck.quack(); // Output: "Quack!"
Create another class that also implements the interface
class RubberDuck implements Duck { quack(): void { console.log("Squeak!"); } }
Use the new class instance as the same type defined by the interface.
let duck: Duck = new RubberDuck(); duck.quack(); // Output: "Squeak!"
As you can see, both MallardDuck and RubberDuck classes implement the Duck interface, and the duck variable can be assigned to instances of both classes. The type is determined by the behaviour (methods and properties) defined in the interface rather than the class.
It's also important to note that in typescript, you can use the typeof keyword to check the type of object in runtime and if the object has the expected method or property.
Example
In this example, the Bird and Plane classes implement the Flyable interface, which requires a fly() method. Both "duck types" can be used interchangeably in the goFly() function. The function doesn't care about the actual type of the object passed to it as long as it has a fly() method that can be called.
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"
On compiling, it will generate the following JavaScript code
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"
Output
The above code will produce the following output
Bird is flying Plane is flying
Example
Overall, duck typing is a powerful programming concept that allows for greater flexibility and reusability in TypeScript code by allowing objects of different types to be used interchangeably as long as they have the same methods and properties. In this example, the Driveable interface, Car and Truck classes show the same thing.
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"
On compiling, it will generate the following JavaScript code
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"
Output
The above code will produce the following output
Car is driving Truck is driving
The main idea behind duck typing is that the code should be written to work with any object with the methods and properties it needs, rather than being written to work with specific objects. This can make the code more flexible and reusable, allowing you to use different types of objects interchangeably without changing the code.