Class Definition and Instantiation: From Objects to Types
In TypeScript, a class is a core concept of object-oriented programming. It builds a reusable object model by defining the blueprint for properties and methods. The definition of a class is essentially creating a template for objects, while instantiation is the process of converting this template into a concrete object.
Classes are declared using the class keyword, with their core function being to define object properties and methods. For example:
class Animal {
name: string;
constructor(n: string) {
this.name = n;
}
greet() {
console.log(`Hello, ${this.name}!`);
}
}
The code above defines an Animal class where the name property is required. The constructor method initializes the object, and the greet method is a public method of the instance. The instantiation process automatically binds this to point to the new object.
Instantiation: Creating Objects
Instantiation involves calling the class's constructor using the new keyword to generate a concrete object. For example:
const cat = new Animal("Whiskers");
cat.greet(); // Outputs "Hello, Whiskers!"
During this process, the constructor of the Animal class is called to create the cat object and assign "Whiskers" to this.name. The instantiated object possesses its own properties and methods and can be further extended.
Type System: From Objects to Types
TypeScript's type system provides powerful support for class definitions and instantiation. Properties and methods of a class can have type annotations to ensure type safety. For example:
class User {
id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
When creating a User instance, TypeScript automatically infers property types based on the parameter types passed. If an unexpected type is passed, TypeScript will report an error. Additionally, type guards can be used to determine if an object is of a specific type, for example:
function isUser(obj: any): obj is User {
return obj instanceof User;
}
This mechanism ensures that instances of the class have explicit type information during type checking.
Inheritance: Building Hierarchical Object Models
Classes support inheritance by creating subclasses using the extends keyword, inheriting properties and methods from the parent class. For example:
class Dog extends Animal {
bark() {
console.log("Woof!");
}
}
The Dog class inherits the name property and greet method from Animal and adds its own bark method. The inheritance chain allows objects to share common logic while calling parent class methods via super.
Type Annotations and Inference
TypeScript type annotations (such as number, string) provide explicit type information for class properties and methods. If not explicitly annotated, TypeScript infers the type based on context. For example:
class User {
constructor(n: string) {
this.name = n;
}
}
When a User instance is created, TypeScript automatically infers the type of name as string based on the passed string argument.
Type Guards and Type Checking
TypeScript type guards (such as instanceof) can be used to determine if an object is of a specific type, ensuring type safety. For example:
function isUser(obj: any): obj is User {
return obj instanceof User;
}
This mechanism is particularly important when dealing with complex types, such as arrays or objects, to avoid type errors.
Static Properties and Methods of Classes
Classes can define static properties (static) and static methods (static), which do not depend on instances but act directly on the class itself. For example:
class Animal {
static defaultColor = "brown";
static greetAll() {
console.log("Hello, all!");
}
}
Animal.defaultColor is a static property shared by all instances; Animal.greetAll is a static method that can be called by all instances.
Class Extension and Decorators
TypeScript supports class extension (class extends) and decorators (@decorator) to enhance class functionality. For example:
class Animal {
@decorator
greet() {
console.log("Hello!");
}
}
Decorators can be used to add metadata, such as logging or validation, improving maintainability of the class.
Summary
Class definition and instantiation form the foundation of object-oriented programming in TypeScript. Through class properties, methods, inheritance, and the type system, developers can build flexible and safe object models. Understanding the lifecycle of a class (from definition to instantiation) and the mechanics of the type system is key to mastering core TypeScript concepts.