Have a question?
Message sent Close

The Ultimate Guide for TypeScript Interview Questions

Explore our detailed guide on TypeScript interview questions and answers designed to prepare you thoroughly for your next job interview. Whether you’re a beginner or an experienced developer looking to refresh your knowledge, this article covers a wide range of topics. From fundamental concepts like TypeScript basics, arrays, and variables, to advanced topics such as decorators, mixins, and design patterns, each question is explained with clarity and accompanied by illustrative examples. Discover how to effectively use TypeScript features like generics, interfaces, and type inference, and gain insights into best practices for leveraging TypeScript over JavaScript in real-world applications. Whether you’re preparing for a junior developer role or aiming for a senior position, this guide equips you with the knowledge and confidence to ace your TypeScript interview.

Why TypeScript?

Developers use TypeScript for a few reasons: it adds type safety to JavaScript, improves developer experience, and is great for collaboration on large projects.

  • Type Safety: JavaScript is dynamically typed, meaning the type of a variable isn’t defined until runtime. This can lead to errors where you accidentally use a variable in a way that wasn’t intended. TypeScript adds static typing, which means you define the type of a variable when you declare it. This helps catch errors early in the development process, before they can cause problems in your application.
  • Developer Experience: TypeScript’s type system provides a lot of benefits for developers. Code editors can use type information to provide features like code completion, inline documentation, and error highlighting. This can make it much faster and easier to write code.
  • Collaboration: TypeScript’s type annotations act as documentation for your code. This makes it easier for other developers to understand your code, which is especially important on large projects with multiple developers.

Overall, TypeScript is a superset of JavaScript that adds optional static typing and other features to help you write JavaScript applications that are more maintainable, scalable, and less error-prone. However, it’s not always necessary, especially for small projects.

typescript interview questions

Typescript Interview Questions for Freshers

Q1. What is TypeScript?
Ans: TypeScript is a strongly typed superset of JavaScript that compiles to plain JavaScript. It adds optional static typing, classes, interfaces, and modules to JavaScript, allowing developers to catch errors early through type checking. Developed and maintained by Microsoft, TypeScript enhances code quality and development efficiency, especially in large-scale applications.

Q2. Explain Arrays in TypeScript?
Ans: Arrays in TypeScript are a collection of elements of the same type. TypeScript enforces the type of elements that the array can hold, ensuring type safety. An array can be declared in two ways: using the square bracket notation or the Array generic type.

Example:

let numbers: number[] = [1, 2, 3, 4];
let fruits: Array<string> = ['apple', 'banana', 'cherry'];

Q3. List the Applications of TypeScript?
Ans: TypeScript is used in various applications, including:

  • Web Development: Frontend frameworks like Angular use TypeScript for building large-scale web applications.
  • Server-Side Development: Node.js applications can be built using TypeScript for better scalability and maintainability.
  • Mobile App Development: Frameworks like NativeScript and Ionic use TypeScript to create cross-platform mobile applications.
  • Enterprise-Level Applications: Large codebases in enterprises benefit from TypeScript’s type safety and tooling.

Q4. Explain the features of Arrays in TypeScript?
Ans: Features of arrays in TypeScript include:

  • Type Safety: Ensures all elements are of a specified type.
  • Multi-dimensional Arrays: Allows arrays of arrays for complex data structures.
  • Array Methods: TypeScript supports all JavaScript array methods like push, pop, map, filter, etc.
  • Tuples: Fixed-size arrays where each element can have a different type.

Example:

let multiDimensionalArray: number[][] = [[1, 2], [3, 4]];
let tuple: [number, string] = [1, 'one'];

Q5. How to declare a variable in TypeScript?
Ans: Variables in TypeScript can be declared using let, const, and var keywords, similar to JavaScript, with an optional type annotation.

Example:

let age: number = 25;
const name: string = 'John';
var isStudent: boolean = true;

Q6. Give an example of generics in TypeScript?
Ans: Generics provide a way to create reusable components that work with any data type. They allow functions, classes, and interfaces to operate with various types while providing type safety.

Example:

function identity<T>(arg: T): T {
  return arg;
}
let output1 = identity<string>("Hello");
let output2 = identity<number>(100);

Q7. Name the access modifiers supported in TypeScript?
Ans: TypeScript supports the following access modifiers:

  • public: Default access modifier; members are accessible from anywhere.
  • private: Members are accessible only within the class they are declared.
  • protected: Members are accessible within the class and its subclasses.

Example:

class Person {
  public name: string;
  private age: number;
  protected address: string;

  constructor(name: string, age: number, address: string) {
    this.name = name;
    this.age = age;
    this.address = address;
  }
}

Q8. Explain the arrow function syntax in TypeScript?
Ans: Arrow functions provide a concise syntax to write functions and lexically bind the this context. They are similar to lambda expressions in other languages.

Example:

let sum = (a: number, b: number): number => {
  return a + b;
};

// Simplified version for single-line functions
let multiply = (a: number, b: number): number => a * b;

Q9. Explain Loops in Typescript?
Ans: TypeScript supports various types of loops:

  • for loop: Iterates over a range of values.
  • for…of loop: Iterates over iterable objects like arrays.
  • for…in loop: Iterates over the properties of an object.
  • while loop: Executes as long as the condition is true.
  • do…while loop: Executes at least once and then continues as long as the condition is true.

Example:

let numbers: number[] = [1, 2, 3, 4, 5];

for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}

for (let num of numbers) {
  console.log(num);
}

let person = { name: "John", age: 30 };
for (let key in person) {
  console.log(`${key}: ${person[key]}`);
}

Q10. What is the use of the tsconfig.json file?
Ans: The tsconfig.json file is used to configure TypeScript compiler options and project settings. It specifies the root files and the compiler options required to compile the project. Common configurations include setting the target ECMAScript version, module system, include/exclude files, and more.

Example:

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

Q11. Why can TypeScript be chosen over JavaScript?
Ans: TypeScript offers several advantages over JavaScript:

  • Static Typing: Catches type-related errors at compile time.
  • Enhanced IDE Support: Provides better autocompletion, refactoring, and navigation.
  • Modern JavaScript Features: Supports ES6 and later features, even if the target environment does not.
  • Scalability: Helps manage and maintain large codebases with ease.
  • Readability and Maintainability: Improved code readability with explicit types and interfaces.

Q12. How to convert a string to a number in TypeScript?
Ans: Converting a string to a number can be done using several methods:

  • Number constructor: Converts string to a number.
  • parseInt or parseFloat: Parses a string and returns an integer or a floating-point number.
  • Unary plus (+) operator: Converts a string to a number.

Example:

let str: string = "123";
let num1: number = Number(str);
let num2: number = parseInt(str);
let num3: number = +str;

Q13. What is meant by contextual typing?
Ans: Contextual typing in TypeScript refers to the type inference mechanism where the type of a variable is determined based on its context. This often occurs in functions, event handlers, and callbacks where the types of parameters are inferred from the context in which they are used.

Example:

window.onmousedown = function(mouseEvent) {
  console.log(mouseEvent.button); // TypeScript infers mouseEvent as MouseEvent
};

Q14. What is the difference between TypeScript and a statically typed language?
Ans: TypeScript is a statically typed superset of JavaScript, meaning it adds static type-checking on top of JavaScript but still allows dynamic typing. In contrast, a purely statically typed language, like Java, enforces type checks strictly at compile time, and all variables must be explicitly typed.

Q15. What is JSX?
Ans: JSX (JavaScript XML) is a syntax extension for JavaScript commonly used with React to describe what the UI should look like. JSX allows you to write HTML-like code within JavaScript, which is then transformed into React elements.

Example:

const element = <h1>Hello, world!</h1>;

Q16. What are import and export keywords in TypeScript?
Ans: The import and export keywords are used to share code between files in TypeScript.

  • export: Used to export variables, functions, classes, interfaces, etc., from a module.
  • import: Used to import variables, functions, classes, interfaces, etc., from other modules.

Example:

// math.ts
export function add(a: number, b: number): number {
  return a + b;
}

// main.ts
import { add } from './math';
console.log(add(2, 3));

Q17. Differentiate between Classes and Interfaces in TypeScript?
Ans:

  • Classes: Can contain properties, methods, constructors, and can implement interfaces. Classes provide a blueprint for creating objects.
  • Interfaces: Define the structure of an object, specifying the types of its properties and methods, but do not provide implementation.

Example:

interface Person {
  name: string;
  age: number;
}

class Employee implements Person {
  name: string;
  age: number;
  employeeId: number;

  constructor(name: string, age: number, employeeId: number) {
    this.name = name;
    this.age = age;
    this.employeeId = employeeId;
  }

  getDetails(): string {
    return `${this.name}, Age: ${this.age}, Employee ID: ${this.employeeId}`;
  }
}

Q18. What are getters/setters?
Ans: Getters and setters are special methods in TypeScript (and JavaScript) used to access and set the values of an object’s properties. They allow controlled access to object properties, enabling validation and computed property values.

  • Getters: Used to retrieve the value of a property. Defined using the get keyword followed by the property name.

Example:

class Rectangle {
  private _width: number;
  private _height: number;

  constructor(width: number, height: number) {
    this._width = width;
    this._height = height;
  }

  get area(): number {
    return this._width * this._height;
  }
}

let rect = new Rectangle(5, 10);
console.log(rect.area); // Outputs: 50
  • Setters: Used to set the value of a property. Defined using the set keyword followed by the property name.

Example:

class Circle {
  private _radius: number;

  constructor(radius: number) {
    this._radius = radius;
  }

  set radius(value: number) {
    if (value < 0) {
      throw new Error('Radius cannot be negative.');
    }
    this._radius = value;
  }
}

let circle = new Circle(5);
circle.radius = 10; // Setting the radius using the setter
console.log(circle.radius); // Outputs: 10

Q19. What is the Declare Keyword in TypeScript?
Ans: In TypeScript, the declare keyword is used to tell the compiler that the variable has been created elsewhere, typically in another JavaScript file. It is used for declaration files that describe the shape of libraries not written in TypeScript.

Example:

declare var jQuery: (selector: string) => any;

Q20. What is an Interface with reference to TypeScript?
Ans: Interfaces in TypeScript define contracts for objects to ensure that certain properties and methods are present. They provide a way to define the structure of an object without implementing it. Interfaces can also be used to extend other interfaces.

Example:

interface Shape {
  color: string;
}

interface Square extends Shape {
  sideLength: number;
}

let square: Square = {
  color: 'blue',
  sideLength: 10,
};

Q21. What is parameter destructuring?
Ans: Parameter destructuring allows you to extract properties from objects and arrays into distinct variables. It simplifies function parameters and makes code more readable by directly referencing object properties inside the function.

Example:

function printPersonInfo({ name, age }: { name: string, age: number }): void {
  console.log(`Name: ${name}, Age: ${age}`);
}

let person = { name: 'John', age: 30 };
printPersonInfo(person); // Outputs: Name: John, Age: 30

Q22. Explain TypeScript Map file?
Ans: TypeScript map files (.map) are generated alongside compiled JavaScript files (.js) when the TypeScript compiler (tsc) is run with the --sourcemap flag. They contain mapping information between the TypeScript source code and the generated JavaScript code, aiding in debugging by allowing the debugger to map the executed JavaScript back to the original TypeScript source.

Q23. Define Lambda function?
Ans: Lambda functions, also known as arrow functions in TypeScript, provide a concise syntax for writing anonymous functions. They are ideal for short, single-expression functions.

Example:

let add = (a: number, b: number): number => a + b;
console.log(add(5, 3)); // Outputs: 8

Q24. Explain Lambda/Arrow function?
Ans: Arrow functions, or lambda functions, are a shorthand syntax for writing function expressions in JavaScript and TypeScript. They have a more concise syntax compared to traditional function expressions and lexically bind the this value.

Example:

let numbers: number[] = [1, 2, 3, 4, 5];
let squaredNumbers = numbers.map(num => num * num);
console.log(squaredNumbers); // Outputs: [1, 4, 9, 16, 25]

Q25. How to create objects in Typescript?
Ans: Objects in TypeScript can be created using object literals or through constructor functions/classes.

Example:

// Using object literal
let person = {
  name: 'Alice',
  age: 30,
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

// Using constructor function
class Car {
  constructor(public make: string, public model: string) {}
}

let myCar = new Car('Toyota', 'Camry');

Q26. Explain Different Data Types in Typescript ?
Ans:

Data TypeDescriptionExample
numberRepresents numeric values (integer or floating-point).let age: number = 30;
stringRepresents textual data enclosed in quotes (single or double).let name: string = 'Alice';
booleanRepresents logical values: true or false.let isValid: boolean = true;
arrayRepresents a collection of elements of the same type.let numbers: number[] = [1, 2, 3, 4];
tupleRepresents an array with fixed number of elements whose types are known.let tuple: [number, string] = [1, 'one'];
enumUsed to define a set of named constants.enum Color { Red, Green, Blue }
anyRepresents any type; useful when the type of a variable is unknown.let value: any = 5;
voidRepresents the absence of a value; used for functions that do not return a value.function logMessage(): void { console.log('Hello'); }
nullRepresents a null value or absence of an object.let data: null = null;
undefinedRepresents an undefined value.let info: undefined = undefined;
objectRepresents any JavaScript object (non-primitive type).let obj: object = { name: 'John' };

Q27. What is meant by Type Inference?
Ans: Type inference in TypeScript is the ability of the compiler to automatically determine the type of a variable based on its initialization value. It allows TypeScript to infer types when types are not explicitly specified, improving code readability and reducing redundancy.

Example:

let number = 5; // TypeScript infers 'number' type for variable 'number'

Q28. What is Anonymous Function in TypeScript?
Ans: Anonymous functions in TypeScript are functions without a named identifier. They are defined using the function keyword without a name and can be assigned to variables or passed as arguments to other functions.

Example:

let greet = function(name: string): void {
  console.log(`Hello, ${name}`);
};
greet('Alice'); // Outputs: Hello, Alice

Q29. What are Decorators?
Ans: Decorators are a design pattern in TypeScript that allow you to add metadata to classes, methods, or properties. They are declared using the @decoratorName syntax and can modify the behavior of the target they are applied to.

Example:

function log(target: any, key: string, descriptor: PropertyDescriptor) {
  let originalMethod = descriptor.value;
  descriptor.value = function(...args: any[]) {
    console.log(`Calling ${key} with arguments ${JSON.stringify(args)}`);
    return originalMethod.apply(this, args);
  };
  return descriptor;
}

class Calculator {
  @log
  add(a: number, b: number): number {
    return a + b;
  }
}

Q30. What are anonymous functions? Provide their syntax in TypeScript?
Ans: Anonymous functions in TypeScript are functions without a named identifier. They can be defined using the function keyword followed by parameters and a function body.

Example:

let add = function(a: number, b: number): number {
  return a + b;
};
console.log(add(5, 3)); // Outputs: 8

Typescript Interview Questions for Experienced

Q31. What are intersection types?
Ans: Intersection types in TypeScript allow you to combine multiple types into one. The resulting type will have all properties and methods from all constituent types.

Example:

interface Employee {
  empId: number;
  name: string;
}

interface Manager {
  empId: number;
  department: string;
}

type ManagerEmployee = Employee & Manager;

let manager: ManagerEmployee = {
  empId: 1001,
  name: 'Alice',
  department: 'HR'
};

Q32. Explain Nullish Coalescing operator?
Ans: The Nullish Coalescing operator (??) in TypeScript returns its right-hand operand when its left-hand operand is null or undefined, otherwise, it returns the left-hand operand.

Example:

let defaultName = 'Guest';
let inputName = null;
let finalName = inputName ?? defaultName;
console.log(finalName); // Outputs: Guest

Q33. Differentiate between the internal module and the external module?
Ans:

  • Internal Module (Namespace):
    • Also known as namespaces, internal modules are used for organizing code and preventing name collisions.
    • They are declared using the namespace keyword.
    • Useful for grouping related functionalities and avoiding global scope pollution.

Example:

namespace Geometry {
  export interface Shape {
    calculateArea(): number;
  }
  export class Circle implements Shape {
    // Implementation
  }
}

External Module (Module):

  • External modules in TypeScript are used for code organization and dependency management.
  • They use import and export statements to specify dependencies between files.
  • Encapsulates code in separate files which can be loaded asynchronously.

Example:

// math.ts
export function add(a: number, b: number): number {
  return a + b;
}

// main.ts
import { add } from './math';
console.log(add(2, 3));

Q34. Explain how you can manage default parameters in a function in TypeScript?
Ans: Default parameters in TypeScript allow you to initialize a function parameter with a default value if no value or undefined is passed. They are declared in the function parameter list using the syntax paramName: type = defaultValue.

Example:

function greet(name: string = 'Guest'): void {
  console.log(`Hello, ${name}`);
}

greet(); // Outputs: Hello, Guest
greet('Alice'); // Outputs: Hello, Alice

Q35. What rules to follow when declaring a variable in TypeScript?
Ans: When declaring variables in TypeScript, follow these rules:

  • Use let for mutable variables and const for constants.
  • Always specify the type of the variable unless it can be inferred.
  • Use camelCase for variable names.
  • Avoid using var unless compatibility with older browsers is required.
  • Follow naming conventions for clarity and maintainability.

Example:

let age: number = 30;
const name: string = 'John';

Q36. What are type assertions in TypeScript?
Ans: Type assertions in TypeScript are a way to tell the compiler about the type of a variable, overriding its inferred type or ensuring that a type is compatible with a certain structure. Type assertions are typically used when TypeScript cannot infer the type or when performing type transformations that are not directly recognized by TypeScript.

Example:

let someValue: any = 'hello world';
let strLength: number = (someValue as string).length;

Q37. Explain the Scope variable?
Ans: The scope of a variable in TypeScript refers to the region of code where the variable is accessible. TypeScript supports block-scoping (variables declared within curly braces {} are limited to that block), function-scoping (variables declared within a function are limited to that function), and global-scoping (variables declared outside any function or block are accessible globally).

Example:

function foo(): void {
  if (true) {
    let message = 'Hello';
    console.log(message); // Accessible within this block
  }
  console.log(message); // Error: 'message' is not defined
}
foo();

Q38. What are abstract classes? When should you use one?
Ans: Abstract classes in TypeScript are base classes that cannot be instantiated directly. They are used to define a common interface for subclasses, which must implement abstract methods defined in the abstract class. Abstract classes provide a way to enforce common behavior across multiple classes.

Example:

abstract class Animal {
  abstract makeSound(): void;
}

class Dog extends Animal {
  makeSound(): void {
    console.log('Woof! Woof!');
  }
}

let myPet: Animal = new Dog();
myPet.makeSound(); // Outputs: Woof! Woof!

Abstract classes should be used when you have a base class that should not be instantiated on its own but provides structure and methods that subclasses must implement.

Q39. What are union types in TypeScript?
Ans: Union types in TypeScript allow a variable to have more than one type. A union type is specified using the | symbol between types. It provides flexibility by allowing variables to hold values of different types at different times.

Example:

let result: number | string;

result = 100; // Valid
console.log(result); // Outputs: 100

result = 'Error'; // Valid
console.log(result); // Outputs: Error

Q40. Differentiate between interface and type statements?
Ans:

  • Interfaces:
    • Used to define the structure of an object and enforce a contract on the shape of an object.
    • Can only represent object types.
    • Can be extended by other interfaces.
    • Can be implemented by classes.

Example:

interface Person {
  name: string;
  age: number;
}

class Student implements Person {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
  • Type Aliases:
    • Used to create a new name for a type. They can represent any valid TypeScript type.
    • Can represent primitive types, union types, tuple types, and more.
    • Cannot be extended or implemented.

Example:

type Point = { x: number, y: number };
type ID = string | number;

let p: Point = { x: 10, y: 20 };
let id: ID = 'abc123';

Q41. Explain how tuple destructuring works in TypeScript?
Ans: Tuple destructuring in TypeScript allows you to unpack values from an array or tuple into distinct variables. It follows the order of elements in the array or tuple for assignment.

Example:

let tuple: [number, string] = [10, 'hello'];
let [num, str] = tuple;
console.log(num); // Outputs: 10
console.log(str); // Outputs: hello

Q42. How to enforce strict null checks in TypeScript?
Ans: Strict null checks in TypeScript can be enforced by setting the strictNullChecks compiler option to true in the tsconfig.json file. This option ensures that variables of types null and undefined can only be assigned to themselves or any.

Example (tsconfig.json):

{
  "compilerOptions": {
    "strictNullChecks": true
  }
}

Q43. What are Rest Parameters in TypeScript?
Ans: Rest parameters in TypeScript allow a function to accept an indefinite number of arguments as an array. They are denoted by three dots (...) followed by the parameter name and must be the last parameter in the function signature.

Example:

function sum(...numbers: number[]): number {
  return numbers.reduce((acc, val) => acc + val, 0);
}

console.log(sum(1, 2, 3)); // Outputs: 6
console.log(sum(1, 2, 3, 4, 5)); // Outputs: 15

Q44. Explain Triple-Slash Directives. List some of the triple-slash directives?
Ans: Triple-slash directives in TypeScript are single-line comments containing a single XML tag directive. They are used to include reference tags for declaration files, dependencies, and module loading.

Example:

/// <reference path="mathFunctions.ts" />
/// <reference types="node" />

Q45. Can TypeScript files be supported from Node Modules? If yes, then how?
Ans: Yes, TypeScript files can be supported from Node Modules by installing type definitions for those modules using npm. TypeScript uses declaration files (.d.ts) to provide type information for libraries and modules that are not written in TypeScript.

Example (installing type definitions for Node.js):

npm install @types/node --save-dev

Q46. What are design patterns?
Ans: Design patterns are reusable solutions to commonly occurring problems in software design. They provide templates for solving particular design problems and promote code reusability, flexibility, and maintainability.

Example: Singleton pattern, Factory pattern, Observer pattern, etc.

Q47. Explain the tuple types in TypeScript?
Ans: Tuple types in TypeScript allow you to express an array where the type of certain elements is known. Tuple types specify the type of each element in the array in a fixed sequence.

Example:

let tuple: [string, number] = ['John', 30];

Q48. Explain the “import type” statement in TypeScript?
Ans: The import type statement in TypeScript is used to import types only, without importing the actual runtime module or code. It is used to ensure that TypeScript understands the shape of types from external modules without importing any JavaScript runtime code.

Example:

import type { Point } from './types';

let point: Point = { x: 10, y: 20 };

Q49. Explain to me the debugging process for a TypeScript file?
Ans: Debugging TypeScript involves compiling TypeScript code to JavaScript with source maps enabled (--sourcemap flag in tsconfig.json). Then, debug the TypeScript code directly using the generated JavaScript files in the browser or IDE debugger while mapping back to the original TypeScript code for breakpoints and stepping through.

Q50. Tell me about “never” in TypeScript?
Ans: In TypeScript, never is a type that represents the type of values that never occur. It is typically used in the following scenarios:

  1. Function Returning Never:
    • Functions that never return a value (or always throw an error) have a return type of never.
    Example:
function throwError(message: string): never {
  throw new Error(message);
}

Never as Type Guard:

  • never is used as a type guard to indicate that a certain condition should never occur.

Example:

function assertNever(value: never): never {
  throw new Error(`Unexpected value: ${value}`);
}

function processValue(x: string | number) {
  if (typeof x === 'string') {
    console.log(x.toUpperCase());
  } else if (typeof x === 'number') {
    console.log(x.toFixed(2));
  } else {
    assertNever(x); // Error: x is inferred as never here
  }
}

Intersection of Contradictory Types:

  • When TypeScript determines that a variable cannot have any possible value, it infers the type as never.

Example:

let impossible: string & number; // Type is 'never' because string and number cannot intersect

Q51. Explain Variables in TypeScript and how to create them?
Ans: Variables in TypeScript are containers for storing data values. They can be created using let, const, or var keywords. Here’s how to create variables in TypeScript:

  1. Using let:
    • Used for mutable variables whose values can change.
    Example:
let name: string = 'Alice';
let age: number = 30;

Using const:

  • Used for constants whose values cannot be reassigned once initialized.

Example:

const PI: number = 3.14;
const URL: string = 'https://example.com';

Using var:

  • Used for declaring variables with broader scope (avoid using var in favor of let and const).

Example:

var count: number = 5;

Q52. Why do we say that TypeScript is an optionally statically typed language?
Ans: TypeScript is considered optionally statically typed because it allows developers to choose whether or not to specify types. TypeScript offers static typing, where types are explicitly declared for variables, function parameters, and return values. However, TypeScript also supports type inference, where the compiler infers types based on the context, if types are not explicitly provided.

  • Optionally Typed:
    • TypeScript allows developers to gradually add type annotations to their codebase. They can start with dynamic typing (any) and progressively add more types as needed.
  • Statically Typed:
    • TypeScript’s type system is checked at compile time, providing benefits such as catching type-related errors early in development and improving code quality and reliability.

By combining optional typing with static type checking, TypeScript offers flexibility and safety, catering to both developers who prefer dynamic typing and those who favor static typing.

Q53. What are Mixins?
Ans: Mixins in TypeScript are a way to combine multiple classes into a single class. They provide a flexible way to reuse code across different classes without using inheritance. Mixins are achieved by merging the functionalities of multiple classes into one using intersection types.

Example:

// Mixin example
class Printable {
  print(): void {
    console.log(this);
  }
}

class Loggable {
  log(): void {
    console.log(`Logged: ${JSON.stringify(this)}`);
  }
}

// Creating a mixin by combining Printable and Loggable
type Mixin = Printable & Loggable;

function applyMixin<T extends Mixin>(baseClass: T): T {
  return baseClass;
}

class MyClass implements Mixin {
  // Implementing both Printable and Loggable
  print: Printable['print'];
  log: Loggable['log'];

  constructor() {
    this.print();
    this.log();
  }
}

let obj = new MyClass();

Q54. How can you create an enum with string values?
Ans: Enums in TypeScript can be created with string values by explicitly assigning string values to each enum member.

Example:

enum Direction {
  Up = 'UP',
  Down = 'DOWN',
  Left = 'LEFT',
  Right = 'RIGHT'
}

let playerDirection: Direction = Direction.Up;
console.log(playerDirection); // Outputs: UP

Q55. What are Objects in TypeScript?
Ans: Objects in TypeScript are instances of classes or data structures that contain properties and methods. They are fundamental to JavaScript and TypeScript, representing real-world entities as data structures.

Example:

// Example of an object
let person = {
  name: 'Alice',
  age: 30,
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

person.greet(); // Outputs: Hello, my name is Alice

Q56. Explain Facade Design Pattern?
Ans: The Facade Design Pattern is a structural design pattern that provides a unified interface to a set of interfaces in a subsystem. It simplifies a complex system by providing a higher-level interface that hides the complexities of the underlying subsystem.

Example:

// Example of a Facade Design Pattern
class BankAccount {
  deposit(amount: number): void {
    console.log(`Depositing ${amount} into bank account.`);
  }
}

class Investment {
  buy(stock: string, quantity: number): void {
    console.log(`Buying ${quantity} shares of ${stock}.`);
  }
}

class FinancialFacade {
  private bank: BankAccount;
  private investment: Investment;

  constructor() {
    this.bank = new BankAccount();
    this.investment = new Investment();
  }

  manageMoney(amount: number, stock: string, quantity: number): void {
    this.bank.deposit(amount);
    this.investment.buy(stock, quantity);
  }
}

// Client code
let manager = new FinancialFacade();
manager.manageMoney(1000, 'AAPL', 10);

In the example, FinancialFacade acts as a facade that hides the complexities of managing money across different subsystems (BankAccount and Investment).

Q57. Explain Type Aliases?
Ans: Type aliases in TypeScript provide a way to create a new name for a type. They are often used to simplify complex type definitions or to give a descriptive name to a union or intersection type.

Example:

type Age = number;
let age: Age = 30;

type Point = {
  x: number;
  y: number;
};
let point: Point = { x: 10, y: 20 };

Type aliases can also be used to define union types, intersection types, and complex object shapes to improve code readability and maintainability.

Q58. Explain Ambients in TypeScript and their use?
Ans: Ambient declarations in TypeScript are used to define the shape of entities (variables, functions, classes) that exist in the runtime but are declared in external JavaScript libraries. They are typically used in declaration files (.d.ts) to provide type information for external libraries that are not written in TypeScript.

Example:

// Example of an ambient declaration for jQuery
declare var jQuery: {
  (selector: string): any;
  fn: any;
  version: string;
};

Ambient declarations allow TypeScript to understand and type-check code that interacts with external libraries.

Q59. Explain noImplicitAny?
Ans: noImplicitAny is a compiler option in TypeScript that prevents the compiler from implicitly inferring the type any for variables whose type cannot be determined. When noImplicitAny is enabled (true), TypeScript requires explicit type annotations for all variables, parameters, and return types.

Example (tsconfig.json):

{
  "compilerOptions": {
    "noImplicitAny": true
  }
}

Q60. Explain the different variants of the for loop in TypeScript?
Ans: In TypeScript, the for loop supports several variants including for...of, for...in, and traditional for loops.

  1. For…of loop:
    • Iterates over the values of an iterable object (like arrays or strings).
    Example:
let numbers = [1, 2, 3, 4];
for (let num of numbers) {
  console.log(num);
}

For…in loop:

  • Iterates over the properties of an object, including inherited properties.

Example:

let obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
  console.log(key, obj[key]);
}

Traditional For loop:

  • A standard for loop with initialization, condition, and increment expressions.

Example:

for (let i = 0; i < 5; i++) {
  console.log(i);
}

Q61. What are the ‘implements’ clauses in TypeScript?
Ans: The implements clause in TypeScript is used to define that a class

implements a particular interface or multiple interfaces. When a class implements an interface, it must provide implementations for all methods defined in that interface.

Example:

// Example of implementing an interface
interface Shape {
  calculateArea(): number;
}
class Circle implements Shape {
  radius: number;
  constructor(radius: number) {
    this.radius = radius;
  }
  calculateArea(): number {
    return Math.PI * this.radius * this.radius;
  }
}
let myCircle = new Circle(5);
console.log(myCircle.calculateArea()); // Outputs: 78.54

In this example:

  • The Circle class implements the Shape interface.
  • It provides an implementation for the calculateArea method defined in the Shape interface.
  • Implementing interfaces in TypeScript helps in achieving consistency across different classes that share common behaviors defined by interfaces.

Q62. What is type aliasing in TypeScript, and how is it used?
Ans: Type aliasing in TypeScript allows developers to create a new name for a type, making complex types more readable and reusable. Type aliases are declared using the type keyword.

Example:

// Example of type aliasing
type Point = {
  x: number;
  y: number;
};

let p: Point = { x: 10, y: 20 };

Type aliases can represent various types including primitive types, union types, intersection types, and more complex object shapes. They improve code readability by providing descriptive names to types.

Q63. What are template literal types?
Ans: Template literal types in TypeScript are string literal types that can include ${} placeholders for interpolation. They allow creating new string types by combining literal strings and placeholders in a type definition.

Example:

// Example of template literal types
type EventName = `click-${string}`;
let eventType: EventName = 'click-submit';
type APIPath<Paths extends string> = `/api/${Paths}`;
let userAPI: APIPath<'users'> = '/api/users';

Template literal types are powerful for creating precise string patterns that can be used as type definitions in TypeScript.

Q64. What is the purpose of noImplicitAny?
Ans: noImplicitAny is a TypeScript compiler option that prevents the compiler from assigning the type any implicitly to variables whose type cannot be determined. Enabling noImplicitAny ensures that all variables, function parameters, and return types have explicit types specified.

Example (tsconfig.json):

{
  "compilerOptions": {
    "noImplicitAny": true
  }
}

The purpose of noImplicitAny is to catch potential runtime errors caused by using any type too liberally in TypeScript code. It encourages developers to explicitly specify types, improving type safety and code clarity.

Q65. What is meant by type inference?
Ans: Type inference in TypeScript is the ability of the TypeScript compiler to automatically deduce or infer the type of a variable based on its initialization value and context. TypeScript uses the initial value assigned to a variable to determine its type.

Example:

let name = 'Alice'; // Type inference infers 'string' for the variable 'name'
let age = 30; // Type inference infers 'number' for the variable 'age'

Type inference helps in reducing the verbosity of code by allowing developers to omit explicit type annotations while still benefiting from the advantages of static typing.

Q66. Explain the various ways to control member visibility in TypeScript?
Ans: In TypeScript, member visibility (or access modifiers) controls the accessibility of class members (properties and methods) from outside the class. TypeScript supports the following access modifiers:

  1. public (default):
    • Public members are accessible from anywhere, both within the class and from outside.
  2. private:
    • Private members are only accessible within the class where they are defined.
  3. protected:
    • Protected members are accessible within the class where they are defined and in derived classes.

Example:

// Example demonstrating access modifiers
class Person {
  public name: string;
  private age: number;
  protected address: string;
  constructor(name: string, age: number, address: string) {
    this.name = name; // Public member
    this.age = age; // Private member
    this.address = address; // Protected member
  }
}
class Employee extends Person {
  constructor(name: string, age: number, address: string) {
    super(name, age, address);
    console.log(this.address); // Accessing protected member in derived class
  }
}
let person = new Person('Alice', 30, '123 Street');
console.log(person.name); // Accessing public member
console.log(person.age); // Error: 'age' is private
console.log(person.address); // Error: 'address' is protected

Access modifiers in TypeScript help in encapsulating and protecting class members, enforcing encapsulation and ensuring data integrity.

Q67. List some of the utility types provided by TypeScript and explain their usage?
Ans: TypeScript provides several utility types out-of-the-box to simplify common type transformations. Some commonly used utility types include:

  1. Partial<T>:
    • Constructs a type with all properties of T set to optional.
    Example:
interface User {
  name: string;
  age: number;
}

function updateUser(user: Partial<User>): void {
  // Can update either 'name' or 'age', or both
}

Required<T>:

  • Constructs a type with all properties of T set to required.

Example:

interface Car {
  make?: string;
  model?: string;
}

function processCar(car: Required<Car>): void {
  // 'make' and 'model' are now required
}

Readonly<T>:

  • Constructs a type with all properties of T set to readonly, preventing modification after assignment.

Example:

interface Config {
  readonly apiKey: string;
  readonly apiUrl: string;
}

Record<K, T>:

  • Constructs a type with a set of properties K of type T.

Example:

type Sports = 'football' | 'basketball' | 'tennis';
type SportsRecord = Record<Sports, number>;

let sportsScores: SportsRecord = {
  football: 2,
  basketball: 1,
  tennis: 0
};

Pick<T, K>:

  • Constructs a type by picking the set of properties K from T.

Example:

interface User {
  id: number;
  name: string;
  age: number;
}

type UserPreview = Pick<User, 'id' | 'name'>;

These utility types enhance code maintainability and readability by providing reusable type transformations.

Q68. Explain how optional chaining works in TypeScript?
Ans: Optional chaining (?.) in TypeScript is a feature that allows you to access properties and methods of an object without needing to explicitly check if each reference in the chain is null or undefined. If any part of the chain is null or undefined, the expression short-circuits and returns undefined.

Example:

interface User {
  id: number;
  name?: string;
  address?: {
    city?: string;
    zipcode?: string;
  };
}

let user: User | null = getUser(); // Function that returns User or null
let cityName = user?.address?.city;
console.log(cityName); // Outputs: undefined if 'user' or 'address' is null or undefined

Optional chaining improves code readability and reduces the need for explicit null checks when accessing nested properties.

Q69. What are string literal types?
Ans: String literal types in TypeScript allow you to specify exact string values that a variable can take. They are defined by using string literal values as types.

Example:

type LogLevel = 'debug' | 'info' | 'warning' | 'error';

function logMessage(level: LogLevel, message: string): void {
  console.log(`[${level.toUpperCase()}] ${message}`);
}
logMessage('debug', 'Debugging information'); // Valid
logMessage('error', 'Error occurred'); // Valid
logMessage('log', 'Logging message'); // Error: 'log' is not assignable to type 'LogLevel'

String literal types help in defining specific sets of allowed values for variables and function parameters, improving type safety and correctness.

Q70. How to make object properties immutable in TypeScript? (hint: readonly)
Ans: In TypeScript, object properties can be made immutable using the readonly keyword. When a property is marked as readonly, its value cannot be changed after initialization.

Example:

interface Config {
  readonly apiUrl: string;
  readonly apiKey: string;
}
let config: Config = {
  apiUrl: 'https://api.example.com',
  apiKey: 'abcd1234'
};
// Cannot reassign readonly properties
config.apiUrl = 'https://new-api.example.com'; // Error: Cannot assign to 'apiUrl' because it is a read-only property

Using readonly ensures that object properties retain their initial values and prevent accidental modifications, enhancing code robustness and reliability.

Click here for more related topics.

Click here to know more about TypeScript.