TypeScript Interview Questions for Developers

Use our engineer-created questions to interview and hire the most qualified TypeScript developers for your organization.

TypeScript

TypeScript is popular choice for companies that value the web development prowess of JavaScript but wanted the security and error prevention that comes with added type safety.

According to the CoderPad 2024 Developer survey, TypeScript is the 7th most in-demand language among technical recruiters and hiring managers.

In order to assess the TypeScript proficiency of developers in coding interviews, we have supplied practical coding tasks and interview queries below. Furthermore, we have delineated a collection of recommended guidelines to guarantee that your interview inquiries effectively gauge the candidates’ TypeScript capabilities.

TypeScript example question

Help us design a parking lot

Hey candidate! Welcome to your interview. Boilerplate is provided. Feel free to change the code as you see fit. To run the code at any time, please hit the run button located in the top left corner.

Goals: Design a parking lot using object-oriented principles

Here are a few methods that you should be able to run:

  • Tell us how many spots are remaining
  • Tell us how many total spots are in the parking lot
  • Tell us when the parking lot is full
  • Tell us when the parking lot is empty
  • Tell us when certain spots are full e.g. when all motorcycle spots are taken
  • Tell us how many spots vans are taking up

Assumptions:

  • The parking lot can hold motorcycles, cars and vans
  • The parking lot has motorcycle spots, car spots and large spots
  • A motorcycle can park in any spot
  • A car can park in a single compact spot, or a regular spot
  • A van can park, but it will take up 3 regular spots
  • These are just a few assumptions. Feel free to ask your interviewer about more assumptions as needed

Junior TypeScript interview questions

Question:
Explain what TypeScript is and how it differs from JavaScript. Provide an example of a TypeScript feature that is not available in JavaScript.

Answer:
TypeScript is a statically typed superset of JavaScript developed by Microsoft. It adds optional static type-checking to JavaScript, allowing developers to define types for variables, function parameters, and return values. The TypeScript code is then compiled to plain JavaScript, which can be executed in any JavaScript runtime.

One of the key differences between TypeScript and JavaScript is the type system. In TypeScript, you can explicitly specify the types of variables and function signatures, which enables catching type-related errors during development and provides better tooling support, such as code completion and type inference.

Example:

// TypeScript
function add(a: number, b: number): number {
  return a + b;
}Code language: JavaScript (javascript)

In this TypeScript example, the function add() explicitly declares the types of its parameters a and b as number, as well as its return type as number. This helps catch potential type errors during development.

In JavaScript, there is no built-in support for static types, so you would write the same function without type annotations:

// JavaScript
function add(a, b) {
  return a + b;
}Code language: JavaScript (javascript)

Question:
The following TypeScript code is intended to implement a class representing a circle. However, it contains a syntax error and doesn’t compile. Identify the error and fix the code.

class Circle {
  private radius: number;

  constructor(radius) {
    this.radius = radius;
  }

  calculateArea() {
    return Math.PI * radius * radius;
  }
}

const circle = new Circle(5);
console.log(circle.calculateArea());Code language: JavaScript (javascript)

Answer:
The error in the code is that the variable radius in the calculateArea() method is not accessed correctly. It should be accessed using this.radius to refer to the class property.

class Circle {
  private radius: number;

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

  calculateArea() {
    return Math.PI * this.radius * this.radius;
  }
}

const circle = new Circle(5);
console.log(circle.calculateArea());Code language: JavaScript (javascript)

In this corrected code, this.radius is used to access the radius property within the calculateArea() method.

Question:
Explain the concept of interfaces in TypeScript and provide an example of how they can be used.

Answer:
Interfaces in TypeScript are used to define the structure of objects or classes. They describe the shape of an object, specifying the names of its properties and their corresponding types. Interfaces enable us to enforce a contract that objects must adhere to, ensuring better type checking and code consistency.

Example:

interface Person {
  firstName: string;
  lastName: string;
  age: number;
  greet: () => void;
}

class Employee implements Person {
  firstName: string;
  lastName: string;
  age: number;

  constructor(firstName: string, lastName: string, age: number) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  greet() {
    console.log(`Hello, my name is ${this.firstName} ${this.lastName}.`);
  }
}

const employee = new Employee("John", "Doe", 30);
employee.greet();Code language: JavaScript (javascript)

In this example, we define an interface Person, specifying the properties firstName, lastName, age, and a function greet(). Then, we create a class Employee that implements the Person interface, ensuring that it has all the required properties and methods defined in the interface.

Question:
The following TypeScript code is intended to create an array of numbers and then filter the even numbers from it. However, it contains a logical error and doesn’t produce the correct result. Identify the error and fix the code.

const numbers: number[] = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter((num) => num % 2);
console.log(evenNumbers);Code language: JavaScript (javascript)

Answer:
The logical error in the code is the condition inside the filter() method. The condition should check for equality to 0 to correctly filter even numbers.

const numbers: number[] = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter((num) => num % 2 === 0);
console.log(evenNumbers);Code language: JavaScript (javascript)

In this corrected code, the filter() method correctly filters the even numbers from the numbers array using the condition num % 2 === 0.

Question:
Explain the concept of generics in TypeScript and provide an example of how they can be used.

Answer:
Generics in TypeScript allow us to create reusable components that can work with different types while preserving type safety. They provide a way to parameterize types, functions, and classes so that they can work with a variety of data types.

Example:

function identity<T>(arg: T): T {
  return arg;
}

const numberValue: number = identity(5);
const stringValue: string = identity("Hello");Code language: JavaScript (javascript)

In this example, we define a generic function identity<T>(arg: T): T. The T within angle brackets represents a generic type. The function takes an argument of type T and returns the same type T. We can call this function with different types, such as number and string, and TypeScript infers the appropriate types for each call.

Question:
The following TypeScript code is intended to merge two objects. However, it contains a syntax error and doesn’t compile. Identify the error and fix the code.

function mergeObjects(obj1: object, obj2: object): object {
  return { ...obj1, ...obj2 };
}

const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = mergeObjects(obj1, obj2);
console.log(mergedObj);Code language: JavaScript (javascript)

Answer:
The syntax error in the code is that the object type doesn’t allow for spread operators. To fix the code, we should use the Record<string, any> type to represent a dictionary-like object with any property names.

function mergeObjects(obj1: Record<string, any>, obj2: Record<string, any>): Record<string, any> {
  return { ...obj1, ...obj2 };
}

const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = mergeObjects(obj1, obj2);
console.log(mergedObj);Code language: JavaScript (javascript)

In this corrected code, we use the Record<string, any> type to represent objects with string keys and any values, allowing us to use spread operators for merging.

Question:
Explain the concept of decorators in TypeScript and provide an example of how they can be used.

Answer:
Decorators in TypeScript are a way to modify classes, methods, or properties at design time. They allow us to enhance the behavior of these elements by attaching metadata or additional functionality.

Example:

function logDecorator(target: any, propertyKey: string, descriptor

: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Calling method ${propertyKey} with arguments ${args}`);
    const result = originalMethod.apply(this, args);
    console.log(`Method ${propertyKey} returned: ${result}`);
    return result;
  };

  return descriptor;
}

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

const calculator = new Calculator();
const sum = calculator.add(5, 3);Code language: JavaScript (javascript)

In this example, we define a decorator function logDecorator. When applied to the add() method of the Calculator class using the @logDecorator syntax, it modifies the behavior of the method. The decorator logs the method call with its arguments and the return value before and after the original method execution.

Question:
The following TypeScript code is intended to define a union type for variables that can be either a string or a number. However, it contains a syntax error and doesn’t compile. Identify the error and fix the code.

let data: string | number;
data = "Hello";
data = 42;
data = true;Code language: JavaScript (javascript)

Answer:
The error in the code is that the variable data is assigned a boolean value, which is not part of the union type. To fix the code, we should only assign values that are either strings or numbers.

let data: string | number;
data = "Hello";
data = 42;Code language: JavaScript (javascript)

In this corrected code, the variable data is correctly assigned values of both types, string and number, which are part of the union type string | number.

Question:
Explain the concept of async/await in TypeScript and how it simplifies asynchronous code. Provide an example of using async/await with Promise.

Answer:
Async/await in TypeScript is a syntactical feature built on top of Promises that simplifies asynchronous code and makes it appear more like synchronous code. It allows you to write asynchronous code using a linear style, making it easier to read and maintain.

Example:

function delay(milliseconds: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
}

async function fetchData(): Promise<string> {
  await delay(2000);
  return "Data fetched successfully!";
}

async function processAsyncData() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (error) {
    console.error("Error fetching data:", error);
  }
}

processAsyncData();Code language: JavaScript (javascript)

In this example, the delay() function returns a Promise that resolves after a given number of milliseconds. The fetchData() function is marked as async and uses await to pause execution until the Promise returned by delay() is resolved. The result is then returned as a string.

The processAsyncData() function is also marked as async, and it calls fetchData() using await, which logs the fetched data after a delay of 2000 milliseconds. If there’s an error in fetching the data, it is caught and logged in the catch block.

The use of async/await here makes the code look like synchronous code, making it easier to understand and reason about asynchronous operations.

Intermediate TypeScript interview questions

Question:
Explain the concept of TypeScript and its benefits over plain JavaScript in a real-world development scenario.

Answer:
TypeScript is a superset of JavaScript that adds static typing and other advanced features to the language. The main benefits of TypeScript over plain JavaScript in a real-world development scenario are:

  1. Static Typing: TypeScript allows developers to specify types for variables, function parameters, and return values. This helps catch type-related errors during development, leading to more robust and maintainable code.
  2. Enhanced Tooling: With static typing, code editors and IDEs can provide better auto-completion, type inference, and refactoring support, leading to increased developer productivity.
  3. Better Collaboration: TypeScript code with explicit types is easier to understand, reducing misunderstandings and improving collaboration among team members.
  4. Improved Code Quality: TypeScript’s static analysis catches potential issues early, reducing the likelihood of bugs and runtime errors in production.
  5. Code Documentation: TypeScript’s type annotations serve as documentation for code, making it easier for developers to understand the purpose and expected usage of functions and variables.
  6. Compatibility with JavaScript: TypeScript is a superset of JavaScript, meaning existing JavaScript code can be gradually migrated to TypeScript, enabling easy adoption.

Question:

The following TypeScript code is intended to calculate the factorial of a given number. However, it contains a logical error and doesn’t produce the correct result. Could you identify the error and fix the code?

function factorial(n: number): number {

 let result = 1;

 for (let i = n; i >= 0; i--) {
   result = result * i;
 }
 return result;
}

const num = 5;

console.log(`Factorial of ${num} is ${factorial(num)}`);Code language: JavaScript (javascript)

Answer:
The logical error is in the for loop’s termination condition. The loop should run until 1 is greater than 0, not when it’s greater or equal than 0. The function above always returns 0, because the loop runs one more time than it should, multiplying the final result by 0.

We could replace the condition “i >= 0” with “i > 0”. But there is even simpler. We can write “i” in the condition. Most of the programming languages (including TypeScript) authorize to use a number in a condition. It will be evaluated as true if the number is different from 0, and false if it is 0. It corresponds to the condition we want.

The correct code is as follows. You may also verify that it works with the specific case of factorial(0), which should return 1.

function factorial(n: number): number {

 let result = 1;

 for (let i = n; i; i--) {
   result = result * i;
 }
 return result;
}

const num = 5;

console.log(`Factorial of ${num} is ${factorial(num)}`);Code language: JavaScript (javascript)

Question:
Explain the concept of interfaces in TypeScript and provide an example of their usage in a real-world application.

Answer:
Interfaces in TypeScript define the structure of objects and act as a contract specifying which properties and methods an object must have. They help in achieving type-checking and allow code to be more maintainable and scalable.

Example of using interfaces in a real-world application:

interface User {
  id: number;
  name: string;
  email: string;
  age?: number; // Optional property
  isAdmin: boolean;
}

function printUserInfo(user: User) {
  console.log(`ID: ${user.id}`);
  console.log(`Name: ${user.name}`);
  console.log(`Email: ${user.email}`);
  if (user.age) {
    console.log(`Age: ${user.age}`);
  }
  console.log(`Is Admin: ${user.isAdmin}`);
}

const user1: User = {
  id: 1,
  name: "John Doe",
  email: "[email protected]",
  age: 30,
  isAdmin: true,
};

printUserInfo(user1);Code language: JavaScript (javascript)

In this example, we define an interface User with specific properties. The printUserInfo() function takes an object that conforms to the User interface and prints its information. The optional property age is denoted by the ? symbol. The user1 object adheres to the User interface and can be passed to the printUserInfo() function for printing the user’s details.

Question:

Question:

The following function gets in parameters an array containing values of miscellaneous types. It tries to convert to number the ones that can be converted, and removes the ones that can not be converted.

The code works, but there is a misconception. Something that is not in accordance to one of the main purpose of TypeScript. Can you find it and fix it?

function keepNumbers(miscData: any[]): any[] {
 const numbers: any[] = [];
 for (let value of miscData) {
   value = parseFloat(value);
   if (!isNaN(value)) {
     numbers.push(value);
   }
 }
 return numbers;
}

const miscData: any[] = [1, 2, "hello", 4.56, "78", "9.99", null, "bye"];
const onlyNumbers = keepNumbers(miscData);

// we get the array: [ 1, 2, 4.56, 78, 9.99 ]
console.log(onlyNumbers);

Answer:

The declared type of the returned array should not be “any”. The function do everything that is needed to return an array of numbers, so it’s worth declaring it. Then, we could use the returned array in other parts of the code where an array of numbers is explicitly needed.

The type must be fixed in the returned value and in the function body.

Here is the fixed code of the function:

function keepNumbers(miscData: any[]): number[] {
 const numbers: number[] = [];
 for (let value of miscData) {
   value = parseFloat(value);
   if (!isNaN(value)) {
     numbers.push(value);
   }
 }
 return numbers;
}

Question:
Explain the concept of generics in TypeScript and provide an example of their usage in a real-world application.

Answer:
Generics in TypeScript allow us to create reusable components or functions that work with different data types while maintaining type safety. They enable us to write more flexible and type-aware code.

Example of using generics in a real-world application:

function reverseArray<T>(array: T[]): T[] {
  return array.reverse();
}

const numbers: number[] = [1, 2, 3, 4, 5];
const reversedNumbers: number[] = reverseArray(numbers);
console.log(reversedNumbers);

const names: string[] = ["John", "Jane", "Alice"];
const reversedNames: string[] = reverseArray(names);
console.log(reversedNames);Code language: HTML, XML (xml)

In this example, we define a generic function reverseArray that can reverse arrays of different data types. The <T> syntax indicates that the function is generic and can work with any data type. The function takes an array of type T and returns an array of the same type. The function is called with both a number array and a string array, demonstrating its flexibility and type safety.

Question:
The following TypeScript code is intended to model a simple bank account with a balance and a method to deposit funds. However, it contains a logical error and doesn’t produce the correct result. Identify the error and fix the code.

class BankAccount {
  private balance: number;

  constructor(initialBalance: number) {
    this.balance = initialBalance;
  }

  deposit(amount: number): void {
    this.balance += amount;
  }

  getBalance(): number {
    return this.balance;
  }
}

const account = new BankAccount(1000);
account.deposit(500);
console.log(`Account balance: ${account.getBalance()}`);Code language: JavaScript (javascript)

Answer:
The code does not contain any logical errors. It models a simple bank account with a balance and a method to deposit funds. The initial balance is set through the constructor, and the deposit() method updates the balance by adding the deposited amount.

When the code runs, it creates a bank account with an initial balance of 1000 and deposits 500 more into

the account. The final balance of the account is then logged to the console.

Question:
Explain the concept of modules in TypeScript and provide an example of their usage in a real-world application.

Answer:
Modules in TypeScript help organize code into separate files, making it easier to manage and reuse code across different parts of an application. They provide a way to encapsulate code and define explicit dependencies between different parts of the application.

Example of using modules in a real-world application:

user.ts:

export interface User {
  id: number;
  name: string;
  email: string;
}

export class UserManager {
  private users: User[] = [];

  addUser(user: User): void {
    this.users.push(user);
  }

  getUserById(id: number): User | undefined {
    return this.users.find((user) => user.id === id);
  }
}Code language: JavaScript (javascript)

app.ts:

import { User, UserManager } from "./user";

const user1: User = { id: 1, name: "John Doe", email: "[email protected]" };
const user2: User = { id: 2, name: "Jane Smith", email: "[email protected]" };

const userManager = new UserManager();
userManager.addUser(user1);
userManager.addUser(user2);

const foundUser = userManager.getUserById(1);
console.log(foundUser);Code language: JavaScript (javascript)

In this example, we have two separate files: user.ts and app.ts. The user.ts file exports the User interface and the UserManager class. The app.ts file imports these exported entities and uses them to manage and retrieve user information.

Question:

The following TypeScript code is intended to model a car object with make, model, and year properties. However, it contains a syntax error and doesn’t compile. Identify the error and fix the code.

class Car {
  constructor(make: string, model: string, year: number) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  getInfo(): string {
    return `${this.make} ${this.model} (${this.year})`;
  }
}

const myCar = new Car("Toyota", "Camry", 2020);
console.log(myCar.getInfo());Code language: JavaScript (javascript)

Answer:
The syntax error in the code is the missing property declarations in the Car class. The correct code is as follows:

class Car {
  make: string;
  model: string;
  year: number;

  constructor(make: string, model: string, year: number) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  getInfo(): string {
    return `${this.make} ${this.model} (${this.year})`;
  }
}

const myCar = new Car("Toyota", "Camry", 2020);
console.log(myCar.getInfo());Code language: JavaScript (javascript)

In this corrected code, the properties make, model, and year are declared in the Car class, allowing them to be accessed and assigned in the constructor and other methods. The code now correctly logs the car information to the console.

Question:
Explain the concept of decorators in TypeScript and provide an example of their usage in a real-world application.

Answer:
Decorators in TypeScript are a powerful feature that allows modifying or annotating classes, methods, properties, or parameters at design time. They provide a way to add metadata or behavior to different parts of a class.

Example of using decorators in a real-world application:

// Decorator function
function logExecutionTime(target: any, key: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function(...args: any[]) {
    const start = Date.now();
    const result = originalMethod.apply(this, args);
    const end = Date.now();
    console.log(`Method ${key} took ${end - start}ms to execute.`);
    return result;
  };
  return descriptor;
}

class MathUtility {
  @logExecutionTime
  static sum(a: number, b: number): number {
    return a + b;
  }
}

console.log(MathUtility.sum(3, 5));Code language: JavaScript (javascript)

In this example, we define a decorator function logExecutionTime. This decorator modifies the behavior of the sum method by measuring its execution time and logging it to the console.

When MathUtility.sum() is called, the decorator is applied, and the modified sum method logs the execution time in milliseconds before returning the result.

Question:
The following TypeScript code is intended to create a generic Dictionary class that stores key-value pairs. However, it contains a syntax error and doesn’t compile. Identify the error and fix the code.

class Dictionary<T> {
  private data: { [key: string]: T } = {};

  setValue(key: string, value: T): void {
    this.data[key] = value;
  }

  getValue(key: string): T | undefined {
    return this.data[key];
  }
}

const myDict = new Dictionary<number>();
myDict.setValue("one", 1);
myDict.setValue("two", 2);

console.log(myDict.getValue("one"));Code language: JavaScript (javascript)

Answer:
The code does not contain any logical errors. It correctly defines a generic Dictionary class that stores key-value pairs of type T. The setValue() method sets the value for a given key, and the getValue() method retrieves the value associated with a given key.

When the code runs, it creates a dictionary of numbers, sets two key-value pairs, and then retrieves the value associated with the key “one,” logging it to the console.

Senior TypeScript interview questions

Question:
Explain the concept of TypeScript and its benefits compared to JavaScript. Provide an example of a TypeScript feature that enhances code maintainability.

Answer:
TypeScript is a statically typed superset of JavaScript that adds optional static type checking to the language. It allows developers to define types for variables, function parameters, and return values, which helps catch type-related errors during development rather than at runtime.

Benefits of TypeScript compared to JavaScript:

  1. Enhanced Type Safety: TypeScript enforces type safety, reducing the chances of runtime errors and improving code reliability.
  2. Better IDE Support: TypeScript provides better tooling support in modern IDEs, offering autocompletion, code navigation, and real-time error checking.
  3. Improved Maintainability: TypeScript’s static typing and type annotations make the codebase more self-documenting and easier to understand, leading to improved code maintainability.
  4. Enhanced Collaboration: TypeScript enhances team collaboration by providing a clear understanding of data structures and interfaces through type declarations.

Example of TypeScript enhancing code maintainability:

// JavaScript code without TypeScript
function calculateTotal(price, quantity) {
  return price * quantity;
}

// TypeScript version with type annotations
function calculateTotal(price: number, quantity: number): number {
  return price * quantity;
}Code language: JavaScript (javascript)

In the TypeScript version, type annotations (: number) are added to the function parameters and the return value. This not only adds type safety but also improves code maintainability by clearly defining the expected types for each parameter and the return value.

Question:
The following TypeScript code is intended to define a class representing a person, but it contains a syntactical error and doesn’t compile. Identify the error and fix the code.

class Person {
  name: string,
  age: number,

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}Code language: JavaScript (javascript)

Answer:
The syntactical error in the code is the incorrect usage of commas (,) instead of semicolons (;) to separate class members. The correct code is as follows:

class Person {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}Code language: JavaScript (javascript)

In this corrected code, semicolons are used to separate class members, ensuring the class definition is valid in TypeScript syntax.

Question:
Theoretical: Explain the concept of interfaces in TypeScript and their significance in maintaining a scalable codebase. Provide an example of using interfaces to define a contract for a complex object.

Answer:
Interfaces in TypeScript are used to define a contract that specifies the structure and types of properties and methods that a class or object must implement. They serve as a blueprint for creating objects with specific shapes, making it easier to manage and maintain a scalable codebase.

Significance of interfaces in maintaining a scalable codebase:

  1. Encourage Consistency: Interfaces encourage consistency by defining a set of rules that must be adhered to by classes or objects that implement them. This consistency leads to more predictable behavior across different parts of the codebase.
  2. Facilitate Collaboration: Interfaces promote collaboration within a development team. Developers can work on different parts of the codebase independently as long as they conform to the defined interfaces.
  3. Enable Abstraction: Interfaces allow developers to abstract away implementation details and focus on defining behavior and contracts. This separation of concerns enhances code readability and maintainability.

Example of using interfaces to define a contract for a complex object:

interface Employee {
  name: string;
  age: number;
  department: string;
  role: string;
  getSalary: () => number;
}

class FullTimeEmployee implements Employee {
  constructor(
    public name: string,
    public age: number,
    public department: string,
    public role: string,
    public monthlySalary: number
  ) {}

  getSalary(): number {
    return this.monthlySalary;
  }
}

class PartTimeEmployee implements Employee {
  constructor(
    public name: string,
    public age: number,
    public department: string,
    public role: string,
    public hourlyRate: number
  ) {}

  getSalary(): number {
    return this.hourlyRate * 160; // Assuming 160 working hours per month
  }
}Code language: PHP (php)

In this example, we define an interface Employee with properties name, age, department, and role, along with a method getSalary(). The FullTimeEmployee and PartTimeEmployee classes implement the Employee interface, ensuring they adhere to the contract defined by the interface. This promotes consistency and scalability in the codebase.

Question:
The following TypeScript code is intended to define a union type, but it contains a syntax error and doesn’t compile. Identify the error and fix the code.

function printID(id: string | number): void {
  console.log(`ID: ${id}`);
}Code language: JavaScript (javascript)

Answer:
The code itself is correct, and there is no syntax error. TypeScript supports union types, as shown in the example, where the parameter id can accept values of either string or number type.

Question:
Explain the concept of generics in TypeScript and their significance in creating reusable and type-safe functions. Provide an example of a generic function that works with different data types.

Answer:
Generics in TypeScript allow for the creation of reusable and type-safe functions and classes that can work with different data types. They enable developers to write code that can handle various types without sacrificing type safety.

Significance of generics in creating reusable and type-safe functions:

  1. Code Reusability: Generics enable the creation of functions and classes that can work with different data types, promoting code reusability across the codebase.
  2. Type Safety: Generics ensure that the type information is preserved throughout the code, avoiding runtime type errors and improving the reliability of the application.
  3. Flexibility: Generics provide flexibility in working with various data structures and containers, making it easier to design more generic algorithms.

Example of a generic function:

function printArray<T>(arr: T[]): void {
  for (const item of arr) {
    console.log(item);
  }
}Code language: JavaScript (javascript)

In this example, we define a generic function printArray() that takes an array of type T and logs each element in the array. The <T> syntax indicates the use of generics. The function can work with arrays of different types, such as number[], string[], or custom data types.

Question:
The following TypeScript code is intended to define an enum representing the days of the week, but it contains a logical error and doesn’t work as expected. Identify the error and fix the code.

enum DaysOfTheWeek {
  Sunday,
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday
}

function getWorkingDay(day: DaysOfTheWeek): string {
  if (day === DaysOfTheWeek.Saturday || day === DaysOfTheWeek.Sunday) {
    return "Weekend";
  } else {
    return "Weekday";
  }
}Code language: JavaScript (javascript)

Answer:
The code itself is correct, and there is no logical error. The enum DaysOfTheWeek is correctly defined, and the

function getWorkingDay() uses the enum values to determine if the given day is a weekend or a weekday.

Question:
Explain the concept of decorators in TypeScript and their significance in extending the functionality of classes and class members. Provide an example of a decorator used to log method calls.

Answer:
Decorators in TypeScript are a language feature inspired by the decorator design pattern. They allow developers to extend or modify the behavior of classes, methods, properties, or parameters at design time.

Significance of decorators in extending class functionality:

  1. Code Separation: Decorators enable separation of cross-cutting concerns, such as logging, caching, and authentication, from the core business logic, leading to more maintainable code.
  2. Reusability: Decorators can be applied to multiple class members, promoting code reusability and avoiding repetitive boilerplate code.
  3. Modularity: By using decorators, you can easily add or remove features to a class without modifying its core implementation, improving code modularity.

Example of a decorator used for logging method calls:

function logMethod(target: any, key: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Calling method ${key} with arguments: ${args}`);
    const result = originalMethod.apply(this, args);
    console.log(`Method ${key} returned: ${result}`);
    return result;
  };

  return descriptor;
}

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

const calculator = new Calculator();
const result = calculator.add(3, 5);
console.log(result); // Output: Calling method add with arguments: 3,5 // Method add returned: 8 // 8Code language: JavaScript (javascript)

In this example, we define a decorator logMethod that logs the method calls and their arguments before and after the method execution. The @logMethod decorator is applied to the add method of the Calculator class, providing enhanced logging functionality without modifying the original method.

Question:
The following TypeScript code is intended to define a function that calculates the sum of elements in an array, but it contains a logical error and doesn’t produce the correct result. Identify the error and fix the code.

function sumArray(arr: number[]): number {
  let sum = 0;
  for (let i = 1; i <= arr.length; i++) {
    sum += arr[i];
  }
  return sum;
}Code language: JavaScript (javascript)

Answer:
The logical error in the code is the incorrect loop condition. Arrays in JavaScript and TypeScript are zero-based, so the loop should start from 0 and end at arr.length - 1. The correct code is as follows:

function sumArray(arr: number[]): number {
  let sum = 0;
  for (let i = 0; i < arr.length; i++) {
    sum += arr[i];
  }
  return sum;
}Code language: JavaScript (javascript)

In this corrected code, the loop starts from 0 and iterates up to arr.length - 1, ensuring all elements in the array are correctly summed.

Question:
Explain the concept of async/await in TypeScript and how it simplifies asynchronous code. Provide an example of using async/await to handle promises.

Answer:
Async/await is a syntactic feature in TypeScript (and JavaScript) that simplifies writing asynchronous code. It allows developers to write asynchronous code in a more synchronous style, making it easier to read and understand.

How async/await simplifies asynchronous code:

  1. Sequential Execution: Async/await allows developers to write asynchronous code that appears to execute sequentially, even though it is non-blocking and doesn’t block the main thread.
  2. Error Handling: With async/await, error handling is more natural, as exceptions can be caught using standard try-catch blocks.
  3. Avoiding Callback Hell: Async/await helps avoid “callback hell” by enabling developers to write asynchronous code in a more linear and readable manner.

Example of using async/await to handle promises:

function fetchData(): Promise<number> {
  return new Promise((resolve) => {
    setTimeout(() => resolve(42), 2000);
  });
}

async function processAsyncData() {
  try {
    const data = await fetchData();
    console.log("Data received:", data);
    // ... other synchronous code ...
  } catch (error) {
    console.error("Error occurred:", error);
  }
}

processAsyncData();Code language: JavaScript (javascript)

In this example, the fetchData() function returns a Promise that resolves with the value 42 after a 2-second delay. The processAsyncData() function uses async/await to handle the Promise returned by fetchData(). The await keyword pauses the execution of the function until the Promise resolves or rejects. The resolved value is then available in the data variable, allowing further synchronous processing. Any errors are caught in the catch block, providing a cleaner and more structured approach to error handling.

Question:
The following TypeScript code is intended to merge two objects into one, but it contains a syntactical error and doesn’t work correctly. Identify the error and fix the code.

function mergeObjects(obj1: object, obj2: object): object {
  return { ...obj1, ...obj2 };
}

const person = { name: "John" };
const details = { age: 30, occupation: "Engineer" };

const merged = mergeObjects(person, details);
console.log(merged);Code language: JavaScript (javascript)

Answer:
The code itself is correct, and there is no syntactical error. TypeScript supports object spread syntax, as shown in the example, where the function mergeObjects() successfully merges two objects person and details into a single object merged.

The output of the code will be:

{ name: 'John', age: 30, occupation: 'Engineer' }Code language: CSS (css)

1,000 Companies use CoderPad to Screen and Interview Developers

Interview best practices for TypeScript roles

For successful TypeScript interviews, taking into account multiple aspects such as the applicant’s experience level and the engineering position is crucial. To guarantee that your TypeScript interview inquiries produce optimal outcomes, we suggest adhering to the following best practices when engaging with candidates:

  • Devise technical queries that correspond with real-world business scenarios within your organization. This approach not only makes the interview more captivating for the applicant but also allows you to more effectively gauge their fit for your team.
  • Encourage the candidate to pose questions throughout the interview and cultivate a cooperative atmosphere.
  • Assess their knowledge of TypeScript best practices, including using strict mode, avoiding the ‘any’ type when possible, and leveraging the power of the type system to write clean, maintainable code.

Moreover, it is essential to follow conventional interview practices when carrying out TypeScript interviews. This encompasses tailoring the question difficulty according to the applicant’s development skill level, offering prompt feedback regarding their application status, and permitting candidates to inquire about the evaluation or collaborating with you and your team.