21
NovTypeScript Classes Explained
TypeScript Classes
Typescript classes are one of TypeScript's most powerful features is its class system. Classes in TypeScript enable you to define blueprints for things, making your code more organized, reusable, and understandable.Imagine you're developing a massive application. TypeScript classes allow you to neatly bundle data and functionality.
So In this TypeScript Tutorial, We are going to explore Typescript classes including constructors, access modifiers etc.
Defining Classes in TypeScript
TypeScript classes build upon JavaScript's class syntax, introducing type annotations and additional features that promote robust and maintainable code.
Class Members
Class members in TypeScript can include properties, methods, and constructors. Each member can have a type annotation to enforce type safety.
class Person {
name: string;
age: number;
greet(): void {
console.log(`Hello, my name is ${this.name}.`);
}
}
Constructors
Constructors are special methods used to initialize class instances. TypeScript allows specifying parameter types and can ownaccess modifiers directly in constructor parameters to define and initialize class members succinctly.
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
Shorthand Syntax with Access Modifiers:
TypeScript allows declaring and initializing class members directly within the constructor parameters using access modifiers (public
, private
, protected
, readonly
).
class Person {
constructor(public name: string, private age: number) {}
}
Access Modifiers
Access modifiers control the visibility of class members, promoting encapsulation and data hiding.
- Public (
public
): Default modifier. Members are accessible from anywhere. - Private (
private
): Members are accessible only within the class. - Protected (
protected
): Members are accessible within the class and its subclasses. - Readonly (
readonly
): Members cannot be reassigned after initialization.
class Person {
public name: string;
private age: number;
protected address: string;
readonly id: number;
constructor(name: string, age: number, address: string, id: number) {
this.name = name;
this.age = age;
this.address = address;
this.id = id;
}
}
Inheritance
TypeScript supports class inheritance, allowing one class to extend another, inheriting its properties and methods. The super
keyword is used to call the parent class's constructor and methods.
class Employee extends Person {
employeeId: number;
constructor(name: string, age: number, address: string, id: number, employeeId: number) {
super(name, age, address, id);
this.employeeId = employeeId;
}
displayEmployeeId(): void {
console.log(`Employee ID: ${this.employeeId}`);
}
}
Getters and Setters
Getters and setters provide controlled access to class properties, enabling validation and encapsulation.
class Person {
private _age: number;
constructor(age: number) {
this._age = age;
}
get age(): number {
return this._age;
}
set age(value: number) {
if (value < 0) {
throw new Error("Age cannot be negative.");
}
this._age = value;
}
}
Static Members
Static members belong to the class itself rather than to instances. They are accessed using the class name.
class MathUtils {
static PI: number = 3.14159;
static calculateCircumference(radius: number): number {
return 2 * MathUtils.PI * radius;
}
}
console.log(MathUtils.PI); // 3.14159
console.log(MathUtils.calculateCircumference(5)); // 31.4159
Abstract Classes
Abstract classes cannot be instantiated directly and are meant to be subclassed. They can contain abstract methods that must be implemented by subclasses.
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log("Moving...");
}
}
class Dog extends Animal {
makeSound(): void {
console.log("Bark!");
}
}
const dog = new Dog();
dog.makeSound(); // Bark!
dog.move(); // Moving...
Implementing Interfaces
Classes can implement interfaces to ensure they adhere to specific contracts, promoting consistency and type safety.
interface IEmployee {
employeeId: number;
getSalary(): number;
}
class Employee implements IEmployee {
constructor(public employeeId: number, private salary: number) {}
getSalary(): number {
return this.salary;
}
}
Generics in Classes
Generics enable classes to operate with various types while maintaining type safety.
class Box<T> {
contents: T;
constructor(value: T) {
this.contents = value;
}
getContents(): T {
return this.contents;
}
}
const numberBox = new Box<number>(123);
console.log(numberBox.getContents()); // 123
const stringBox = new Box<string>("Hello");
console.log(stringBox.getContents()); // Hello
Examples
Example 1: Basic Class
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): void {
console.log(`Hello, my name is ${this.name}.`);
}
}
const person = new Person("John", 30);
person.greet(); // Hello, my name is John.
Example 2: Inheritance and Access Modifiers
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
move(): void {
console.log(`${this.name} is moving.`);
}
}
class Dog extends Animal {
constructor(name: string) {
super(name);
}
bark(): void {
console.log(`${this.name} is barking.`);
}
}
const dog = new Dog("Buddy");
dog.move(); // Buddy is moving.
dog.bark(); // Buddy is barking.
Example 3: Implementing Interfaces
interface Vehicle {
speed: number;
accelerate(): void;
}
class Car implements Vehicle {
speed: number = 0;
accelerate(): void {
this.speed += 10;
console.log(`Speed: ${this.speed}`);
}
}
const car = new Car();
car.accelerate(); // Speed: 10
Example 4: Abstract Classes and Generics
abstract class Shape {
abstract calculateArea(): number;
describe(): void {
console.log("This is a shape.");
}
}
class Circle extends Shape {
constructor(public radius: number) {
super();
}
calculateArea(): number {
return Math.PI * this.radius ** 2;
}
}
const circle = new Circle(5);
console.log(circle.calculateArea()); // 78.53981633974483
Differences Between JavaScript and TypeScript Classes
While TypeScript classes are similar to JavaScript ES6 classes, they introduce several key differences:
- Type annotations, enforcing static types.
- Access modifiers (
public
,private
,protected
), enhancing encapsulation. - Generics support in classes and methods.
- Abstract classes for better inheritance modeling.
In detailed
Feature | JavaScript Classes | TypeScript Classes |
Type Annotations | Not available. JavaScript does not support type annotations. | Supports type annotations for properties, parameters, and return values, enhancing type safety. |
Access Modifiers | JavaScript classes do not have access to modifiers. | Provides public , private , and protected access modifiers to control visibility of class members. |
Read-only Properties | No built-in support for read-only properties. | Supports the readonly modifier to create immutable properties. |
Interface Implementation | JavaScript classes cannot implement interfaces. | TypeScript classes can implement interfaces, ensuring they conform to specific contracts. |
Generics | JavaScript does not support generics. | TypeScript supports generics, allowing classes to be more flexible while maintaining type safety. |
Compile-time Type Checking | No type checking at compile-time. Errors are caught at runtime. | TypeScript performs type checking at compile-time, preventing many runtime errors. |
Constructor Shorthand | No shorthand for defining and initializing properties in the constructor. | Supports parameter properties, where properties are automatically declared and initialized from constructor parameters. |
Abstract Classes | No support for abstract classes. | Supports abstract classes and methods, enforcing subclasses to implement specific behaviors. |
Decorators | Decorators are not natively supported. Experimental via external libraries. | TypeScript provides experimental support for decorators using the experimentalDecorators option. |
Static Typing | JavaScript is dynamically typed. | TypeScript is statically typed, requiring explicit type declarations or type inference. |
Default Access Modifier | Class members are public by default. | Same as JavaScript; class members are public unless specified otherwise. |
Strict Null Checks | No strict null checks. Null or undefined can be assigned to variables freely. | TypeScript has strict null checks, preventing null or undefined from being assigned to variables without proper handling. |
Advanced Features
1. Decorators
Decorators in TypeScript are a special kind of declaration that can be applied to classes, methods, properties, or parameters to modify their behavior.
2. Mixins
Mixins allow the composition of reusable functionalities across multiple classes, bypassing traditional inheritance.
Best Practices
- Use access modifiers to control the visibility and access of class members.
- Have abstract classes and interfaces to define reusable and consistent code structures.
- Employ generics for flexibility while maintaining type safety.
- Write concise and self-documenting code by using getters and setters.
- Avoid deeply nested inheritance hierarchies to prevent tight coupling and maintain simplicity.
Conclusion
TypeScript classes extend the capabilities of JavaScript by introducing static typing, access modifiers, and advanced OOPs features such as abstract classes and generics. Mastering TypeScript classes allows developers to write more predictable, scalable, and maintainable code. By adhering to best practices, TypeScript developers can harness the full power of object-oriented programming.
FAQs
Take our Typescript skill challenge to evaluate yourself!
In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.