Object Oriented Programming In Typescript Interview Questions
Comprehensive object oriented programming in typescript interview questions and answers for TypeScript.
Prepare for your next job interview with expert guidance.
TypeScript supports single inheritance using the 'extends' keyword. A class can inherit properties and methods from another class, and can override methods from the parent class. Multiple inheritance is achieved through interfaces. Example: class Employee extends Person { constructor(name: string, private department: string) { super(name); } }
Parameter properties are a TypeScript shorthand that allows you to both declare and initialize class members in the constructor parameters. They're created by adding an access modifier to the parameter. Example: class Person { constructor(private name: string, public age: number) {} } This creates and initializes 'name' and 'age' properties automatically.
Classes can implement interfaces using the 'implements' keyword. The class must provide implementations for all properties and methods defined in the interface. Multiple interfaces can be implemented using comma separation. Example: interface Printable { print(): void; } class Document implements Printable { print() { console.log('printing...'); } }
Static members (properties and methods) belong to the class itself rather than instances of the class. They're defined using the 'static' keyword and are accessed using the class name. Example: class Calculator { static PI = 3.14159; static add(x: number, y: number): number { return x + y; } }
Method overriding allows a subclass to provide a specific implementation of a method that is already defined in its parent class. TypeScript ensures type safety in overridden methods. Example: class Animal { makeSound() { return 'noise'; } } class Dog extends Animal { override makeSound() { return 'woof'; } }
Polymorphism in TypeScript can be achieved through method overriding and interfaces. It allows objects of different classes to be treated as objects of a common base class or interface. Example: interface Shape { area(): number; } class Circle implements Shape { area() { return Math.PI * r * r; } } class Rectangle implements Shape { area() { return w * h; } }
Abstract methods are methods declared in abstract classes without implementation. They must be implemented by derived classes. They're used when a base class knows a method is needed but specific implementation depends on the derived class. Example: abstract class Shape { abstract calculateArea(): number; }
The Factory pattern provides an interface for creating objects without specifying exact classes. In TypeScript, it's implemented using abstract classes or interfaces with factory methods. Example: abstract class Creator { abstract createProduct(): Product; } class ConcreteCreator extends Creator { createProduct(): Product { return new ConcreteProduct(); } }
The 'super' keyword is used to call methods or access properties on the parent class. It's commonly used in constructors of derived classes and when overriding methods. Example: class Child extends Parent { constructor(name: string) { super(name); } override getName(): string { return 'Child: ' + super.getName(); } }
TypeScript supports three access modifiers: public (default, accessible everywhere), private (only within the declaring class), and protected (within declaring class and derived classes). These modifiers help enforce encapsulation and control access to class members. Example: class Employee { private salary: number; protected id: string; public name: string; }
Private constructors prevent class instantiation from outside the class. They're commonly used in singleton pattern implementation or utility classes that shouldn't be instantiated. Example: class Utility { private constructor() {} static helper() { return 'help'; } }
Composition involves creating complex objects by combining simpler ones, while inheritance creates relationships between classes. Composition is often preferred as it provides more flexibility and looser coupling. Example of composition: class Car { private engine: Engine; private wheels: Wheel[]; constructor() { this.engine = new Engine(); this.wheels = [new Wheel(), new Wheel(), new Wheel(), new Wheel()]; } }
TypeScript classes are blueprints for creating objects that extend JavaScript classes with additional features like access modifiers (public, private, protected), parameter properties, abstract classes, and interface implementation. They provide compile-time type checking and better encapsulation. Example: class Person { private name: string; constructor(name: string) { this.name = name; } }
The 'readonly' modifier makes class properties immutable after initialization. They must be initialized at declaration or in the constructor. Example: class Config { readonly apiKey: string; constructor(key: string) { this.apiKey = key; } } Once set, readonly properties cannot be changed.
Mixins are a way to combine multiple classes into one. TypeScript implements mixins using class expressions and a helper function. Example: type Constructor<T = {}> = new (...args: any[]) => T; function Timestamped<TBase extends Constructor>(Base: TBase) { return class extends Base { timestamp = Date.now(); }; }
The Observer pattern is implemented using interfaces for Subject and Observer, with the Subject maintaining a list of observers and notifying them of changes. Example: interface Observer { update(data: any): void; } class Subject { private observers: Observer[] = []; addObserver(observer: Observer) { this.observers.push(observer); } notify(data: any) { this.observers.forEach(observer => observer.update(data)); } }
Abstract classes are base classes that cannot be instantiated directly and may contain abstract methods that must be implemented by derived classes. They're defined using the 'abstract' keyword. They're useful for defining common behavior while forcing specific implementations in subclasses. Example: abstract class Animal { abstract makeSound(): void; move() { console.log('moving...'); } }
TypeScript supports JavaScript's get and set accessors with additional type safety. They allow you to add logic when accessing or modifying class properties. Example: class Circle { private _radius: number; get radius(): number { return this._radius; } set radius(value: number) { if (value >= 0) this._radius = value; } }
Singleton pattern ensures a class has only one instance. In TypeScript, it's implemented using a private constructor and static instance. Example: class Singleton { private static instance: Singleton; private constructor() {} static getInstance(): Singleton { if (!Singleton.instance) { Singleton.instance = new Singleton(); } return Singleton.instance; } }
TypeScript supports method overloading through function declarations with different parameter types or numbers. Implementation is done with a single function that handles all overloads. Example: class Calculator { add(x: number, y: number): number; add(x: string, y: string): string; add(x: any, y: any): any { return x + y; } }
Protected constructors allow instantiation only from within the class itself or its derived classes. This pattern is useful for creating base classes that shouldn't be instantiated directly but can be extended. Example: class Base { protected constructor() {} } class Derived extends Base { constructor() { super(); } }
Index signatures in classes allow you to define dynamic properties with a specific type. They're defined using [key: string]: type syntax. Example: class Dictionary { [key: string]: string; constructor() {} add(key: string, value: string) { this[key] = value; } }
Type guards in class hierarchies help narrow down types when working with inheritance. The instanceof operator is commonly used as a type guard. Example: class Animal {} class Dog extends Animal { bark() {} } function makeNoise(animal: Animal) { if (animal instanceof Dog) { animal.bark(); } }