logo
Product
Product Tour
Aptitude Tests Coding Tests Psychometric Tests Personality Tests
Campus Hiring Features Proctoring Enterprise
Test Library Questions Pricing
Resources
Blog Case studies Books Tools
About us
Login
Log In

Search test library by skills or roles
⌘ K
logo
Assessment Platform Aptitude Tests Coding Tests Psychometric Tests Personality Tests

TRY FOR FREE

TypeScript Interview Questions For Freshers
  1. How do you declare variables in TypeScript?
  2. What are interfaces in TypeScript and how are they used?
  3. How do you define a function in TypeScript?
  4. How do you define an array in TypeScript?
  5. What is a class in TypeScript and how is it used?
  6. How do you declare a constant in TypeScript?
  7. How do you define a type alias in TypeScript?
  8. What is the difference between let and var in TypeScript?
  9. How do you compile TypeScript into JavaScript?
  10. What is the difference between "any" and "unknown" in TypeScript?
  11. How do you handle null and undefined in TypeScript?
  12. How do you declare a function type in TypeScript?
  13. What is the "readonly" keyword in TypeScript and how is it used?
  14. What is a type assertion in TypeScript and how is it different from type casting?
  15. What is the difference between "interface" and "class" in TypeScript?
  16. How do you declare a tuple in TypeScript?
  17. What is a type guard in TypeScript and how is it used?
  18. How do you use the "in" operator in TypeScript?
  19. What is the "keyof" operator in TypeScript and how is it used?
TypeScript Intermediate Interview Questions
  1. What is a module in TypeScript and how is it used?
  2. How do you use namespaces in TypeScript?
  3. What are decorators in TypeScript and how are they used?
  4. How do you handle optional parameters in a function in TypeScript?
  5. How do you handle default parameters in a function in TypeScript?
  6. How do you handle rest parameters in a function in TypeScript?
  7. How do you define an enum in TypeScript?
  8. How do you define a generic type in TypeScript?
  9. What are union types in TypeScript and how are they used?
  10. How do you define an abstract class in TypeScript?
  11. What is a conditional expression in TypeScript and how is it used?
  12. How do you declare a type for a React component in TypeScript?
  13. How do you define an intersection type in TypeScript?
  14. How do you handle type widening in TypeScript?
  15. What is the "never" type in TypeScript and how is it used?
  16. How do you declare a type for a function that returns a Promise in TypeScript?
  17. What is the difference between a module and a namespace in TypeScript?
  18. How do you use the "as const" keyword in TypeScript?
  19. How do you define a mapped type in TypeScript?
  20. What is the difference between "private" and "protected" access modifiers in TypeScript?
TypeScript Interview Questions For Experienced
  1. What are type guards in TypeScript and how are they used?
  2. What are conditional types in TypeScript and how are they used?
  3. How do you use mapped types in TypeScript?
  4. What is a type assertion in TypeScript and how is it used?
  5. What is a declaration file in TypeScript and how is it used?
  6. How do you use intersection types in TypeScript?
  7. What are type predicates in TypeScript and how are they used?
  8. How do you use type inference in TypeScript?
  9. What is a type alias and how is it different from an interface in TypeScript?
  10. What is a module loader in TypeScript and how does it work?
  11. What is a conditional type constraint in TypeScript and how is it used?
  12. What is the "infer" keyword in TypeScript and how is it used?
  13. How do you use the "exclude" and "extract" utility types in TypeScript?
  14. What is a recursive type in TypeScript and how is it used
  15. What is a distributive conditional type in TypeScript and how is it used?
  16. What is the "type" keyword in TypeScript and how is it used?
  17. What is the "import type" statement in TypeScript and how is it used?
  18. What is the "const" assertion in TypeScript and how is it used?
  19. How do you use the "readonly" utility type in TypeScript?
  20. What is the "Partial" type in TypeScript and how is it used?


Interview Questions

TypeScript interview questions with detailed answers

Most important TypeScript interview questions for freshers, intermediate and experienced candidates. The important questions are categorized for quick browsing before the interview or to act as a detailed guide on different topics TypeScript interviewers look for.

TypeScript Online Test

TypeScript Interview Questions For Freshers

How do you declare variables in TypeScript?

View answer

Hide answer

In TypeScript, you can declare variables using the let, var, or const keyword. let and const are block-scoped, while var is function-scoped.


let myVariable: string = "Hello, world!"; // Declares a variable of type string
const myConstant: number = 42; // Declares a constant of type number
var myVar: boolean = true; // Declares a variable of type boolean

You can also declare variables without specifying their type. TypeScript can infer the type of the variable from its value:


let myVariable = "Hello, world!"; // TypeScript infers that myVariable is of type string

What are interfaces in TypeScript and how are they used?

View answer

Hide answer

An interface in TypeScript is a way to define a contract for an object. It specifies the properties and methods that the object must have.


interface Person {
  firstName: string;
  lastName: string;
  age?: number; // Optional property
  sayHello: () => void; // Method that returns void
}

In the example above, we define an interface Person with four properties: firstName, lastName, age (which is optional), and sayHello (which is a method that returns void).

We can then use this interface to define objects that implement the Person interface:


const person: Person = {
  firstName: "John",
  lastName: "Doe",
  sayHello: () => {
    console.log(`Hello, my name is ${person.firstName} ${person.lastName}.`);
  },
};

How do you define a function in TypeScript?

View answer

Hide answer

In TypeScript, you can define functions using the function keyword. You can also specify the types of the function parameters and return type:


function add(x: number, y: number): number {
  return x + y;
}

In the example above, we define a function add that takes two parameters x and y of type number and returns a value of type number.

How do you define an array in TypeScript?

View answer

Hide answer

In TypeScript, you can define an array using the Array keyword or the shorthand [] notation. You can also specify the type of the array:


const numbers: Array<number> = [1, 2, 3, 4, 5]; // Array of numbers
const names: string[] = ["John", "Doe", "Jane", "Smith"]; // Array of strings

What is a class in TypeScript and how is it used?

View answer

Hide answer

A class in TypeScript is a blueprint for creating objects. It is a way to define a complex object with its properties and methods.

Here's an example of a class in TypeScript:


class Person {
  private firstName: string;
  private lastName: string;
  public age: number;

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

  public getFullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
}

const person = new Person("John", "Doe", 30);
console.log(person.getFullName()); // Output: John Doe
console.log(person.age); // Output: 30

In the example above, we define a class Person with three properties: firstName, lastName, and age. We also define a constructor that sets these properties when a new object is created.

We then define a method getFullName that returns the full name of the person.

Finally, we create a new object person of type Person and call the getFullName method on it.

How do you declare a constant in TypeScript?

View answer

Hide answer

In TypeScript, you can declare a constant using the const keyword. Once a value is assigned to a constant, it cannot be changed:


const PI: number = 3.14;

How do you define a type alias in TypeScript?

View answer

Hide answer

A type alias in TypeScript is a way to create a new name for a type. It can be used to simplify complex types or to give a more descriptive name to a type.


type Point = { x: number; y: number }; // Type alias for a point
type Shape = { points: Point[] }; // Type alias for a shape

In the example above, we define two type aliases: Point and Shape. Point is an object with two properties x and y of type number, and Shape is an object with a property points which is an array of Point objects.

What is the difference between let and var in TypeScript?

View answer

Hide answer

In TypeScript, let and var are used to declare variables. The key difference between them is their scope.

let is block-scoped, which means that it is only accessible within the block in which it is defined.

var, on the other hand, is function-scoped, which means that it is accessible within the entire function in which it is defined.


function example() {
  let x = 1;
  var y = 2;
  if (true) {
    let x = 3; // This is a new variable
    var y = 4; // This reassigns the existing variable
  }
  console.log(x); // Output: 1
  console.log(y); // Output: 4
}

In the example above, we define two variables x and y using let and var respectively. We then define a block using the if statement, inside which we define a new variable x using let and reassign the existing variable y using var. Finally, we log the values of x and y to the console, which shows that the let variable x is block-scoped and the var variable y is function-scoped.

How do you compile TypeScript into JavaScript?

View answer

Hide answer

To compile TypeScript into JavaScript, you need to use the TypeScript compiler tsc. You can install it using npm:


npm install -g typescript

Once installed, you can use the tsc command to compile a TypeScript file:


tsc myfile.ts

This will generate a JavaScript file with the same name as the TypeScript file:


myfile.ts
myfile.js

By default, tsc will compile to ECMAScript 3. You can specify a different target ECMAScript version using the --target flag:


tsc myfile.ts --target es6

You can also watch for changes in your TypeScript files and automatically compile them using the --watch flag:


tsc myfile.ts --watch

In addition, you can specify a configuration file tsconfig.json to customize the compiler options. Here's an example of a tsconfig.json file:


{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "sourceMap": true},
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

In the example above, we specify the compiler options target as es6, module as commonjs, and sourceMap as true. We also specify the files to include and exclude from the compilation process. You can then run tsc without any arguments to compile all the files according to the options in the configuration file:


tsc

This will compile all the files in the src directory and output the compiled JavaScript files in the same directory.

What is the difference between "any" and "unknown" in TypeScript?

View answer

Hide answer

In TypeScript, any and unknown are used to represent values with unknown or dynamic types. However, there is a subtle difference between the two.

The any type is used to represent any value, and it can be assigned to any other type without type-checking. This means that it bypasses TypeScript's type-checking, allowing for flexibility but also potentially leading to errors. For example:


let x: any = 5;
x = "hello";
x = [1, 2, 3];

On the other hand, the unknown type is also used to represent any value, but it is not as permissive as any. When using unknown, you must perform type-checking or type assertions before you can assign it to another variable. This allows for more safety in your code. For example:


let y: unknown = 5;
// y = "hello"; // Type error
if (typeof y === "number") {
  const z = y + 1;
}

In short, use any if you want maximum flexibility and don't mind the potential for errors. Use unknown if you want to ensure type safety and require type-checking before assignment.

How do you handle null and undefined in TypeScript?

View answer

Hide answer

In TypeScript, null and undefined are treated as separate types that represent absence or lack of a value. They can be used to declare variables, parameters, and function return types.

To handle null and undefined in TypeScript, you can use the union type | to declare a variable that can accept both a value and null or undefined. For example:


let x: string | null | undefined;
x = "hello";
x = null;
x = undefined;

Alternatively, you can use the non-null assertion operator ! to assert that a value is not null or undefined. For example:


function foo(x: string | null | undefined) {
  const y = x!;
  // ...
}

Another option is to use optional chaining ?. and nullish coalescing ?? operators to handle null and undefined values. For example:


const x = { y: { z: 5 } };
const z = x?.y?.z ?? 0; // 5

const foo: string | undefined = undefined;
const bar = foo ?? "default"; // "default"

How do you declare a function type in TypeScript?

View answer

Hide answer

In TypeScript, you can declare a function type using the () syntax. The parameters and return type are specified within the parentheses.

For example, to declare a function that takes two number parameters and returns a number, you would write:


type AddFunction = (a: number, b: number) => number;

const add: AddFunction = (a, b) => a + b;

Alternatively, you can use the interface syntax to declare a function type:


interface AddFunction {
  (a: number, b: number): number;
}

const add: AddFunction = (a, b) => a + b;

What is the "readonly" keyword in TypeScript and how is it used?

View answer

Hide answer

In TypeScript, the readonly keyword is used to declare a read-only property of an object. This means that the property can only be initialized once and cannot be modified thereafter.

For example:


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

const person: Person = { name: "John", age: 30 };
person.name = "Mike"; // Error: Cannot assign to 'name' because it is a read-only property.

The readonly keyword can also be used with arrays:


const arr: readonly number[] = [1, 2, 3];
arr[0] = 4; // Error: Index signature in type 'readonly number[]' only permits reading.

It is important to note that readonly only applies to the top-level property of an object or array. It does not make the property's contents read-only. To make the contents read-only, you can use the ReadonlyArray type or a type assertion.

What is a type assertion in TypeScript and how is it different from type casting?

View answer

Hide answer

In TypeScript, a type assertion is a way to tell the compiler that you know the type of a value more precisely than it does. It is used to convert a value to a specific type, without changing the underlying value.

Type assertions are written using the <type> or as type syntax. For example:


const x: unknown = "hello";
const y = (x as string).toUpperCase();

In this example, we assert that x is a string by using the as keyword. We then call the toUpperCase() method on y, which is guaranteed to be a string.

Type assertions are different from type casting in other languages, as they do not actually change the type of the underlying value. Type casting can lead to runtime errors, whereas type assertions only affect compile-time type checking.

What is the difference between "interface" and "class" in TypeScript?

View answer

Hide answer

In TypeScript, both interface and class are used to define object types. However, there are some key differences between the two.

An interface is a purely structural type that defines a contract for the shape of an object. It is not compiled into any code and does not have an implementation. Interfaces can be extended, and can also be implemented by classes.

For example:


interface Person {
  name: string;
  age: number;
  greet(): void;
}

A class, on the other hand, is a blueprint for creating objects that have both state and behavior. It can have properties, methods, and a constructor, and can be instantiated using the new keyword. Classes can also implement interfaces.

For example:


class Person implements Person {
  constructor(public name: string, public age: number) {}

  greet() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

const john = new Person("John", 30);
john.greet(); // Hello, my name is John and I am 30 years old.

In general, use an interface when you just need to define the shape of an object, and use a class when you need to create objects that have behavior and state.

How do you declare a tuple in TypeScript?

View answer

Hide answer

In TypeScript, a tuple is a fixed-length array with a specific element type for each position in the array. To declare a tuple, use the [type1, type2, ...] syntax.

For example:


type ThreeNumbers = [number, number, number];

const numbers: ThreeNumbers = [1, 2, 3];

You can access individual elements in a tuple using indexing:

const x= numbers[0]; // x is of type 'number'

You can also use the length property to ensure that you only access elements that exist


const y = numbers[numbers.length]; // Error: Element implicitly has an 'any' type because index expression is not of type 'number'.

Note that tuples in TypeScript are intended for cases where you need a fixed number of elements of known types. If you need a collection that can grow or shrink, use an array instead.

What is a type guard in TypeScript and how is it used?

View answer

Hide answer

In TypeScript, a type guard is a way to narrow the type of a variable or parameter based on a certain condition. It allows you to write more precise and type-safe code.

There are several ways to implement a type guard, but the most common way is to use the typeof, instanceof, or in operator.

For example, to check if a value is a string, you can use the typeof operator:


function isString(value: unknown): value is string {
  return typeof value === "string";
}

const x: unknown = "hello";

if (isString(x)) {
  const y = x.toUpperCase(); // y is of type 'string'
}

In this example, the isString function is a type guard that checks if the value parameter is a string. It returns a boolean, and the value is string syntax tells the compiler that the return value should be treated as a type guard.

The typeof operator can be used to check for string, number, boolean, symbol, and undefined.

The instanceof operator can be used to check if an object is an instance of a class:


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

function isPerson(value: unknown): value is Person {
  return value instanceof Person;
}

const x: unknown = new Person();

if (isPerson(x)) {
  const y = x.name; // y is of type 'string'
}

In this example, the isPerson function is a type guard that checks if the value parameter is an instance of the Person class.

The in operator can be used to check if a property exists in an object:


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

function hasName(value: unknown): value is { name: string } {
  return typeof value === "object" && "name" in value;
}

const x: unknown = { name: "John", age: 30 };

if (hasName(x)) {
  const y = x.name; // y is of type 'string'
}

In this example, the hasName function is a type guard that checks if the value parameter has a name property.

How do you use the "in" operator in TypeScript?

View answer

Hide answer

The in operator is used to check if a property exists in an object. It is often used in conditional statements to perform different actions based on whether a property exists or not.

Here's an example of how to use the in operator in TypeScript:


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

function printProperty(person: Person, property: string) {
  if (property in person) {
    console.log(person[property]);
  } else {
    console.log(`${property} does not exist in person`);
  }
}

const person: Person = {
  name: 'John',
  age: 30
};

printProperty(person, 'name'); // Output: John
printProperty(person, 'email'); // Output: email does not exist in person

In this example, we have an interface Person with two properties name and age. We also have a function printProperty that takes a Person object and a property string. If the property exists in the object, we print its value. Otherwise, we print a message saying that the property does not exist in the object.

We create a person object and call the printProperty function twice with the name and email properties. The first call prints the value of the name property, while the second call prints a message saying that the email property does not exist in the person object.

What is the "keyof" operator in TypeScript and how is it used?

View answer

Hide answer

The keyof operator in TypeScript is used to extract the names of the properties of an object or interface as a union type. This can be useful in many scenarios, such as when you want to create a type-safe way of accessing the properties of an object.

Here's an example of how to use the keyof operator in TypeScript:


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

type PersonKeys = keyof Person;

function getProperty(person: Person, key: PersonKeys) {
  return person[key];
}

const person: Person = {
  name: 'John',
  age: 30,
  email: '[email protected]'
};

const name = getProperty(person, 'name'); // Type: string
const age = getProperty(person, 'age'); // Type: number
const email = getProperty(person, 'email'); // Type: string
const invalid = getProperty(person, 'invalid'); // Error: Argument of type 'invalid' is not assignable to parameter of type 'keyof Person'

In this example, we have an interface Person with three properties name, age, and email. We also have a type PersonKeys that uses the keyof operator to extract the keys of the Person interface as a union type.

We have a function getProperty that takes a Person object and a key of type PersonKeys. The function returns the value of the property with the given key.

We create a person object and call the getProperty function three times with the name, age, and email keys. The function returns the value of the corresponding property and assigns the correct type to the variables.

We also try to call the getProperty function with an invalid key, which results in a TypeScript error saying that the argument is not assignable to the PersonKeys type.

TypeScript Intermediate Interview Questions

What is a module in TypeScript and how is it used?

View answer

Hide answer

In TypeScript, a module is a way of organizing and encapsulating code. A module can contain classes, functions, variables, and other code that can be exported for use in other modules.

To use a module in TypeScript, you can create a new file and define your module using the export keyword. You can then import the module in another file using the import keyword.

Here's an example of how to define and use a module in TypeScript:


// File: myModule.ts

export const PI = 3.14;

export function double(value: number): number {
  return value * 2;
}

export class MyClass {
  private _name: string;

  constructor(name: string) {
    this._name = name;
  }

  public sayHello(): void {
    console.log(`Hello, ${this._name}!`);
  }
}

// File: main.ts

import { PI, double, MyClass } from './myModule';

console.log(PI); // 3.14

console.log(double(2)); // 4

const myClass = new MyClass('John');
myClass.sayHello(); // Hello, John!

In the example above, we defined a module named myModule that exports a constant PI, a function double, and a class MyClass. We then imported these exports in another file named main.ts using the import keyword.

How do you use namespaces in TypeScript?

View answer

Hide answer

In TypeScript, a namespace is a way of grouping related code together. Namespaces help prevent naming collisions by providing a unique scope for the code they contain.

To use a namespace in TypeScript, you can define it using the namespace keyword. You can then declare functions, classes, and other code inside the namespace.

Here's an example of how to define and use a namespace in TypeScript:


// File: myNamespace.ts

namespace MyNamespace {
  export const PI = 3.14;

  export function double(value: number): number {
    return value * 2;
  }

  export class MyClass {
    private _name: string;

    constructor(name: string) {
      this._name = name;
    }

    public sayHello(): void {
      console.log(`Hello, ${this._name}!`);
    }
  }
}

export default MyNamespace;

// File: main.ts

import MyNamespace from './myNamespace';

console.log(MyNamespace.PI); // 3.14

console.log(MyNamespace.double(2)); // 4

const myClass = new MyNamespace.MyClass('John');
myClass.sayHello(); // Hello, John!

In the example above, we defined a namespace named MyNamespace that exports a constant PI, a function double, and a class MyClass. We then imported the default export of the myNamespace module and used the namespace as a property of the imported object.

What are decorators in TypeScript and how are they used?

View answer

Hide answer

Decorators are a way of adding metadata to classes, functions, and other TypeScript declarations. Decorators can be used to modify the behavior of a declaration, such as adding logging, validation, or authorization checks.

To use a decorator in TypeScript, you can define a function that takes the target declaration as an argument and returns a new declaration with the desired metadata.

Here's an example of how to define and use a decorator in TypeScript:


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

  descriptor.value = function (...arguments: any[]) {
console.log(Calling ${name} with arguments: ${JSON.stringify(arguments)});
const result = originalMethod.apply(this, arguments);
console.log(Result: ${result});
return result;
};

return descriptor;
}

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

const myClass = new MyClass();
myClass.add(2, 3); // Calling add with arguments: [2,3]
// Result: 5

In the example above, we defined a decorator named log that logs the name of the method and its arguments before and after it's called. We then applied the log decorator to the add method of a MyClass class. When we called the add method, the decorator added the logging behavior.

How do you handle optional parameters in a function in TypeScript?

View answer

Hide answer

In TypeScript, you can make a parameter optional in a function by adding a question mark ? after the parameter name. Optional parameters are useful when you want to provide a default value or when the parameter is not always necessary for the function to work correctly.

Here is an example:


function addNumbers(x: number, y?: number): number {
  if (y) {
    return x + y;
  } else {
    return x;
  }
}

console.log(addNumbers(1));      // Output: 1
console.log(addNumbers(1, 2));   // Output: 3

In the example above, the y parameter is optional. If y is not provided, the function will return the value of x. If y is provided, the function will add x and y together and return the result.

How do you handle default parameters in a function in TypeScript?

View answer

Hide answer

Default parameters are values that are automatically assigned to a function parameter if the caller of the function does not provide a value for that parameter. To define a default parameter in TypeScript, you can simply assign a value to the parameter.

Here is an example:


function sayHello(name: string = "World"): void {
  console.log(`Hello, ${name}!`);
}

sayHello();        // Output: Hello, World!
sayHello("John");  // Output: Hello, John!

In the example above, the name parameter has a default value of "World". If no argument is passed to sayHello, it will print "Hello, World!". If an argument is passed, it will print "Hello, [argument]!".

How do you handle rest parameters in a function in TypeScript?

View answer

Hide answer

Rest parameters allow a function to accept an indefinite number of arguments as an array. In TypeScript, you can declare a rest parameter by using the spread operator ... followed by the name of the array that will contain the rest of the arguments.

Here is an example:


function printNumbers(...numbers: number[]): void {
  for (let i = 0; i < numbers.length; i++) {
    console.log(numbers[i]);
  }
}

printNumbers(1, 2, 3);         // Output: 1 2 3
printNumbers(4, 5, 6, 7, 8);   // Output: 4 5 6 7 8

In the example above, the printNumbers function accepts any number of arguments and prints them out one by one using a for loop.

How do you define an enum in TypeScript?

View answer

Hide answer

An enum is a type in TypeScript that allows you to define a set of named constants. Enums are useful when you have a small, fixed set of values that are related to each other.

Here is an example:


enum Color {
  Red,
  Green,
  Blue
}

let myColor: Color = Color.Green;
console.log(myColor);  // Output: 1 (index of Green in the Color enum)

In the example above, we define an enum called Color with three named constants: Red, Green, and Blue. We then assign the myColor variable to Color.Green, which has an index of 1 in the enum.

How do you define a generic type in TypeScript?

View answer

Hide answer

Generic types allow you to create reusable code that works with different types. In TypeScript, you can define a generic type by using angle brackets < and ‘ `` ’ to specify one or more type parameters. You can then use these type parameters to define the types of the function arguments, return values, or class properties.

Here is an example:


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

console.log(identity<string>("Hello"));  // Output: Hello
console.log(identity<number>(42));        // Output: 42

In the example above, we define a generic function called identity that takes a type parameter T. The function returns the argument arg of type T. When we call the function, we specify the type of the argument using angle brackets. The compiler infers the return type based on the argument type.

What are union types in TypeScript and how are they used?

View answer

Hide answer

Union types allow a variable or parameter to have more than one type. In TypeScript, you can define a union type by using the pipe | symbol to separate the types.

Here is an example:


function printId(id: number | string): void {
  console.log(`ID is: ${id}`);
}

printId(101);           // Output: ID is: 101
printId("202");         // Output: ID is: 202

In the example above, the printId function accepts a parameter id that can be either a number or a string. We use the | symbol to define a union type. When we call the function with a number or a string, it prints out the ID.

Union types are also useful when you want to define a variable or property that can have different types at runtime.

How do you define an abstract class in TypeScript?

View answer

Hide answer

An abstract class is a class that cannot be instantiated directly. Instead, it serves as a base class for other classes to extend and implement. In TypeScript, you can define an abstract class by using the abstract keyword before the class definition.

Here is an example:


abstract class Animal {
  abstract makeSound(): void;
  move(): void {
    console.log("Moving...");
  }
}

class Cat extends Animal {
  makeSound(): void {
    console.log("Meow");
  }
}

let myCat: Animal = new Cat();
myCat.makeSound();  // Output: Meow
myCat.move();       // Output: Moving...

In the example above, we define an abstract class called Animal that has an abstract method called makeSound and a non-abstract method called move. We then define a concrete class called Cat that extends the Animal class and implements the makeSound method. We create an instance of Cat and assign it to a variable of type Animal. When we call the makeSound and move methods, they are called on the Cat instance.

What is a conditional expression in TypeScript and how is it used?

View answer

Hide answer

A conditional expression in TypeScript is a way to define a type based on a condition. It is also known as a ternary operator. The syntax for a conditional type is T extends U ? X : Y, where T is the type to be checked, U is the type to be compared against, X is the type to be returned if the condition is true, and Y is the type to be returned if the condition is false.


type User = {
  name: string;
  age: number;
};

type Admin = {
  name: string;
  age: number;
  role: string;
};

type UserRole<T> = T extends { role: infer R } ? R : "user";

type UserWithRole = UserRole<User>; // "user"
type AdminWithRole = UserRole<Admin>; // string

In the above example, we define two types User and Admin which both have a name and age property, but only Admin has a role property. We then define a type UserRole using a conditional expression, which checks if the input type has a role property. If it does, the type of that property is returned, otherwise the string "user" is returned. We then use this type to define UserWithRole and AdminWithRole, which have types "user" and string respectively.

How do you declare a type for a React component in TypeScript?

View answer

Hide answer

To declare a type for a React component in TypeScript, we can use the React.FC (Function Component) type. The React.FC type takes a generic type argument which represents the props that the component expects.


import React from "react";

type Props = {
  name: string;
  age: number;
};

const MyComponent: React.FC<Props> = ({ name, age }) => {
  return (
    <div>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
    </div>
  );
};

In the above example, we define a type Props which has a name property of type string and an age property of type number. We then define a React component MyComponent using the React.FC type and passing in Props as the generic type argument. The component receives the name and age props as destructured arguments and returns some JSX.

How do you define an intersection type in TypeScript?

View answer

Hide answer

To define an intersection type in TypeScript, we use the & (ampersand) operator. An intersection type represents a type which has all the properties of two or more other types.


type User = {
  name: string;
  age: number;
};

type Admin = {
  role: string;
};

type UserWithRole = User & Admin;

const user: UserWithRole = {
  name: "John",
  age: 30,
  role: "admin"
};

In the above example, we define two types User and Admin. We then define a type UserWithRole which is an intersection of User and Admin. This means that a UserWithRole object must have all the properties of both User and Admin. We then create a user object of type UserWithRole which has a name, age, and role property.

How do you handle type widening in TypeScript?

View answer

Hide answer

Type widening in TypeScript occurs when a variable is assigned a value that has a more general type than the declared type. For example, if we declare a variable with the type string but assign it a value of type string | number, the type of the variable will be widened to string | number. This can cause unexpected behavior in our code, so it's important to know how to handle type widening.

One way to handle type widening in TypeScript is to use type assertions to narrow the type of the variable. We can do this by adding the as keyword followed by the desired type after the variable name.


let str = "hello";
let widenedStr = str || 42; // Type is widened to string | number

let narrowStr = str as string; // Type is narrowed back to string

In the above example, we declare a variable str with the type string and assign it the value "hello". We then assign widenedStr to str || 42, which has the more general type string | number, causing the type of widenedStr to be widened to string | number. We then use a type assertion to narrow the type of str back to string and assign it to narrowStr.

What is the "never" type in TypeScript and how is it used?

View answer

Hide answer

The never type in TypeScript represents a value that never occurs. It is used to indicate that a function will never return, or that a type cannot have any values. The never type is a subtype of all other types, which means that any type is assignable to never, but never is not assignable to any type except never itself.


function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {}
}

type EmptyObject = Record<never, never>;

const neverValue: never = throwError("Something went wrong");

In the above example, we define a function throwError which throws an error and has a return type of never, since it never returns normally. We also define a function infiniteLoop which contains an infinite loop and also has a return type of never. We then define a type EmptyObject which is an object with no properties, and we use the Record utility type with never as the key and value types. Finally, we create a variable neverValue which is assigned the return value of throwError, which is of type never.

How do you declare a type for a function that returns a Promise in TypeScript?

View answer

Hide answer

To declare a type for a function that returns a Promise in TypeScript, we can use the Promise type with a generic type argument that represents the type of the resolved value.


function fetchUser(): Promise<{ name: string; age: number }> {
  return fetch("/api/user")
    .then(response => response.json())
    .then(data => ({ name: data.name, age: data.age }));
}

In the above example, we define a function fetchUser which returns a Promise that resolves to an object with a name property of type string and an age property of type number. We use the fetch API to make a request to an API endpoint and return the parsed JSON response as a Promise.

What is the difference between a module and a namespace in TypeScript?

View answer

Hide answer

In TypeScript, a module is a way to organize code into reusable units, while a namespace is a way to organize code into named groups. The main difference between the two is that a module can contain both code and type definitions, while a namespace can only contain code.

A module can be defined using the export keyword before a declaration, which makes it available for use in other modules. Modules can also have a default export, which can be used to export a single value from the module.


// my-module.ts
export function greet(name: string) {
  console.log(`Hello, ${name}!`);
}

export default function sayGoodbye(name: string) {
  console.log(`Goodbye, ${name}!`);
}

In the above example, we define a module my-module which exports a function greet and a default function sayGoodbye. The greet function takes a name argument of type string and logs a greeting to the console, while the sayGoodbye function takes a name argument of type string and logs a goodbye message to the console.

Modules can then be imported and used in other modules:


// app.ts
import { greet } from "./my-module";
import sayGoodbye from "./my-module";

greet("Alice"); // logs "Hello, Alice!"
sayGoodbye("Bob"); // logs "Goodbye, Bob!"

A namespace, on the other hand, is defined using the namespace keyword and can only contain code:


// my-namespace.ts
namespace MyNamespace {
  export function greet(name: string) {
    console.log(`Hello, ${name}!`);
  }
}

In the above example, we define a namespace MyNamespace which contains a function greet that takes a name argument of type string and logs a greeting to the console. Namespaces can be used to group related code and avoid naming collisions, but they cannot be exported and used in other files like modules can.

How do you use the "as const" keyword in TypeScript?

View answer

Hide answer

The as const keyword in TypeScript is used to create a readonly version of a value or object literal. This is useful when we want to ensure that a value or object cannot be modified later, as it can help catch errors and make our code more robust.


const myArray = ["hello", "world"] as const;
const myObject = { name: "Alice", age: 30 } as const;

In the above example, we define a constant myArray which is an array of strings, and a constant myObject which is an object with name and age properties. We use the as const keyword to create readonly versions of these values, which prevents them from being modified later.

How do you define a mapped type in TypeScript?

View answer

Hide answer

A mapped type in TypeScript is a way to create a new type by transforming the properties of an existing type. This is done using the Record utility type, which takes two type arguments: the first is the type of the keys, and the second is the type of the values.


type MyMappedType<T> = {
  [P in keyof T]: T[P] | null;
};

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

type NullableUser = MyMappedType<User>;

In the above example, we define a type MyMappedType which takes a generic type argument T and creates a new type by mapping each property of T to a union type of the property type and null. We then define an interface User with name and age properties, and use MyMappedType to create a new type NullableUser which is the same as **User**, but with each property now possibly **null`**

What is the difference between "private" and "protected" access modifiers in TypeScript?

View answer

Hide answer

In TypeScript, the private and protected access modifiers can be used to restrict access to class members.

The private keyword restricts access to a member to only the containing class. This means that the member cannot be accessed or modified from outside the class, including from subclasses.


class MyClass {
  private myPrivateProperty: string = "private";

  public getMyPrivateProperty() {
    return this.myPrivateProperty;
  }
}

const myClassInstance = new MyClass();
console.log(myClassInstance.myPrivateProperty); // Error: Property 'myPrivateProperty' is private

In the above example, we define a class MyClass with a private property myPrivateProperty. We then create an instance of the class and try to access the private property, which results in an error.

The protected keyword restricts access to a member to the containing class and its subclasses. This means that the member can be accessed and modified from within the class and any subclasses that extend it, but not from outside the class hierarchy.


class MyParentClass {
  protected myProtectedProperty: string = "protected";
}

class MyChildClass extends MyParentClass {
  public getMyProtectedProperty() {
    return this.myProtectedProperty;
  }
}

const myParentClassInstance = new MyParentClass();
console.log(myParentClassInstance.myProtectedProperty); // Error: Property 'myProtectedProperty' is protected

const myChildClassInstance = new MyChildClass();
console.log(myChildClassInstance.getMyProtectedProperty()); // logs "protected"

In the above example, we define a parent class MyParentClass with a protected property myProtectedProperty, and a child class MyChildClass which extends the parent class and has a method that accesses the protected property. We then create instances of both classes and try to access the protected property from outside the class hierarchy, which results in an error for the parent class instance but works for the child class instance.

Overall, private restricts access to a member to only the containing class, while protected allows access from within the class and its subclasses.

TypeScript Interview Questions For Experienced

What are type guards in TypeScript and how are they used?

View answer

Hide answer

Type guards in TypeScript are a way to narrow down the type of a variable or expression within a conditional block. They allow the compiler to make assumptions about the type of a value based on certain checks, which can then be used to enable or disable certain operations.

For example, we can use a type guard to check if an object has a certain property before accessing it:


interface Car {
  make: string;
  model: string;
  year: number;
}

function isCar(value: any): value is Car {
  return value && typeof value === "object" && "make" in value && "model" in value && "year" in value;
}

function getCarMake(car: any): string {
  if (isCar(car)) {
    // TypeScript now knows that `car` has all the properties of a `Car` object
    return car.make;
  }

  throw new Error("Not a valid car object");
}

In the above example, we define an interface Car, a type guard isCar that checks if a given value has all the properties of a Car object, and a function getCarMake that uses the type guard to safely access the make property of the input object.

Type guards can also be used to narrow down the type of a variable based on its value or the value of another variable, using the typeof, instanceof, and in operators:


function isNumber(value: any): value is number {
  return typeof value === "number";
}

function isString(value: any): value is string {
  return typeof value === "string";
}

function isArrayOfStrings(value: any): value is string[] {
  return Array.isArray(value) && value.every((item) => isString(item));
}

function formatValue(value: string | number | string[]) {
  if (isNumber(value)) {
    // `value` is now narrowed down to type `number`
    return value.toFixed(2);
  }

  if (isString(value)) {
    // `value` is now narrowed down to type `string`
    return value.toUpperCase();
  }

  if (isArrayOfStrings(value)) {
    // `value` is now narrowed down to type `string[]`
    return value.join(", ");
  }

  throw new Error("Invalid value");
}

In the above example, we define several type guards that check if a value is a number, string, or array of strings, and a function formatValue that uses the type guards to format the input value based on its type.

What are conditional types in TypeScript and how are they used?

View answer

Hide answer

Conditional types in TypeScript allow us to write types that depend on other types. They are used to express different type relationships, such as checking if a type has a certain property, or if it is a union or intersection of types. The syntax of a conditional type looks like this:


type MyType<T> = T extends SomeType ? TrueType : FalseType;

This type definition means that if the type T extends the SomeType type, the resulting type is TrueType, otherwise it is FalseType. Here's an example:


type ExtractStrings<T> = T extends string | string[] ? T : never;

type StringOrStringArray = string | string[];
type OnlyStrings = ExtractStrings<StringOrStringArray>; // string

In the above example, we define a generic type ExtractStrings that checks if the type T is a string or an array of **string**s, and returns the original type if it matches, otherwise it returns never. We then use this type to extract only the string type from a union of string and string[].

Conditional types are especially useful in situations where we want to infer a type based on a condition, such as when writing a generic utility function that can handle different types.

How do you use mapped types in TypeScript?

View answer

Hide answer

Mapped types in TypeScript allow us to transform an existing type into a new type by mapping over its properties. The syntax of a mapped type looks like this:


type NewType = { [Property in ExistingType]: NewPropertyType };

This type definition means that we create a new type NewType with properties that have the same name as the properties in the ExistingType, but with a different type NewPropertyType. Here's an example:


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

type PersonPartial = { [P in keyof Person]?: Person[P] };

const person: PersonPartial = { name: "John" };

In the above example, we define an interface Person with properties name and age, and use a mapped type to create a new type PersonPartial that has the same properties as Person, but with an optional modifier ?. We then create a variable of type PersonPartial with only the name property, and it is allowed because that property is optional.

Mapped types are useful for creating new types that are based on existing types but with some modifications, such as making properties optional, required, or readonly.

What is a type assertion in TypeScript and how is it used?

View answer

Hide answer

A type assertion in TypeScript is a way to tell the compiler that we know the type of a variable or expression better than it does. It is used to override the inferred or declared type of a variable or expression with a different type. The syntax of a type assertion looks like this:


const someValue: any = "hello";
const strLength: number = (someValue as string).length;

In the above example, we define a variable someValue of type any with a string value, and use a type assertion to tell the compiler that we know the type of someValue is actually a string. We then use the length property of the string to get its length and store it in a variable strLength.

Type assertions are useful when we want to bypass the type checker and assert that a value has a specific type. However, we should use them sparingly and only when we are absolutely sure

What is a declaration file in TypeScript and how is it used?

View answer

Hide answer

A declaration file in TypeScript is a file that provides type information for a JavaScript library or module that does not have its own type definitions. It is used to enable TypeScript to understand the shape of a JavaScript library or module and provide type-checking and code completion for it. A declaration file has the extension .d.ts and contains only type information, not actual code.

Here's an example of a declaration file for the lodash library:


declare function chunk<T>(array: ArrayLike<T>, size?: number): T[][];
declare function compact<T>(array: ArrayLike<T | false | null | 0 | ''>): T[];
declare function concat<T>(array: ArrayLike<T>, ...values: Array<ConcatArray<T> | T>): T[];
// ... and so on

In the above example, we declare the function signatures for some of the functions in the lodash library. This allows TypeScript to understand the type information for those functions and provide code completion and type-checking for them.

Declaration files are usually provided by the library or module author, but they can also be created by users of the library or module. There are also community-driven repositories of declaration files for popular JavaScript libraries and modules, such as DefinitelyTyped.

How do you use intersection types in TypeScript?

View answer

Hide answer

Intersection types in TypeScript allow us to combine multiple types into a single type that has all the properties and methods of each type. The resulting type can be used as if it is a union of the original types, but with more restrictive properties. The syntax of an intersection type looks like this:


type NewType = Type1 & Type2 & Type3;

This type definition means that we create a new type NewType that has all the properties and methods of Type1, Type2, and Type3. Here's an example:


interface Dog {
  bark(): void;
}

interface Cat {
  meow(): void;
}

type DogCat = Dog & Cat;

const dogCat: DogCat = {
  bark() { console.log("woof"); },
  meow() { console.log("meow"); }
};

In the above example, we define two interfaces Dog and Cat with their respective methods, and use an intersection type to create a new type DogCat that has both methods. We then create a variable of type DogCat and assign an object with both methods.

Intersection types are useful when we want to create a new type that has the properties of multiple types, but with more restrictive properties, such as requiring all methods to be present in the resulting type.

What are type predicates in TypeScript and how are they used?

View answer

Hide answer

Type predicates in TypeScript allow us to narrow down the type of a variable or expression based on a condition. They are used to check if a variable or expression has a certain property or type, and if it does, to treat it as that type. The syntax of a type predicate looks like this:


function isType(arg: any): arg is SomeType {
  return arg.hasOwnProperty("someProperty");
}

This function definition means that if the argument arg has a property named someProperty, the result is true, otherwise it is false. We then use this function as a type predicate to narrow down the type of a variable or expression. Here's an example:

interface Cat {
  meow(): void;
}

function isCat(arg: any): arg is Cat {
  return arg && typeof arg.meow === "function";
}

function doSomething(catOrDog: Cat or Dog) {
if (isCat(catOrDog)) {
// catOrDog is now of type Cat
catOrDog.meow();
} else {
// catOrDog is now of type Dog
catOrDog.bark();
}
}

In the above example, we define an interface Cat with a method meow, and a type predicate function isCat that checks if an object has a meow method. We then use the type predicate function in a function that takes either a Cat or Dog argument, and we use an if statement to check if the argument is a Cat, and if it is, we call the meow method, otherwise we call the bark method.

Type predicates are useful when we want to narrow down the type of a variable or expression based on a condition, and provide more specific type information to TypeScript.

How do you use type inference in TypeScript?

View answer

Hide answer

Type inference in TypeScript is the ability of the TypeScript compiler to automatically deduce the type of a variable or expression based on its usage. This allows us to write less code and still have the benefits of static type checking.

Type inference works by analyzing the usage of a variable or expression and inferring its type based on the context. For example, if we initialize a variable with a number, TypeScript will infer the type of the variable as number. Similarly, if we call a function that returns a string, TypeScript will infer the return type of the function as string.

Here's an example:

const num = 42; // TypeScript infers the type as number
const str = "hello"; // TypeScript infers the type as string

function add(a: number, b: number) {
  return a + b;
}

const result = add(2, 3); // TypeScript infers the type as number

In the above example, we define two variables num and str and initialize them with a number and a string, respectively. TypeScript infers the types of the variables based on their initialization values. We then define a function add that takes two numbers and returns their sum. When we call the add function with two numbers, TypeScript infers the type of the result variable as number.

Type inference is a powerful feature of TypeScript that allows us to write less code and still have the benefits of static type checking.

What is a type alias and how is it different from an interface in TypeScript?

View answer

Hide answer

A type alias in TypeScript is a name given to a type definition. It is used to simplify complex types and make them more readable. Type aliases can be used to define any type, including union types, intersection types, function types, and object types.

The syntax of a type alias looks like this:


type NewType = OriginalType;

This type definition means that we create a new type NewType that is an alias for the OriginalType. Here's an example:


type Employee = {
  name: string;
  age: number;
  salary: number;
};

type Manager = Employee & {
  department: string;
};

const john: Employee = { name: "John", age: 35, salary: 50000 };
const jane: Manager = { name: "Jane", age: 40, salary: 75000, department: "Sales" };

In the above example, we define a type alias Employee for an object that has three properties: name, age, and salary. We then define a type alias Manager that extends the Employee

type by adding a department property. We can use the Employee and Manager types to declare variables and TypeScript will check if the properties are of the correct type.

An interface in TypeScript is a type definition that describes the shape of an object. It is used to define the structure of an object and its properties, as well as the types of those properties. An interface can be used to define any type, including object types, function types, and class types.

The syntax of an interface looks like this:


interface NewType {
  property1: Type1;
  property2: Type2;
  // ...
}

This type definition means that we create a new type NewType that has properties property1 and property2, with types Type1 and Type2, respectively. Here's an example:


interface Employee {
  name: string;
  age: number;
  salary: number;
}

interface Manager extends Employee {
  department: string;
}

const john: Employee = { name: "John", age: 35, salary: 50000 };
const jane: Manager = { name: "Jane", age: 40, salary: 75000, department: "Sales" };

In the above example, we define an interface Employee for an object that has three properties: name, age, and salary. We then define an interface Manager that extends the Employee interface by adding a department property. We can use the Employee and Manager interfaces to declare variables and TypeScript will check if the properties are of the correct type.

The main difference between a type alias and an interface in TypeScript is that a type alias can be used to define any type, including union types, intersection types, and function types, while an interface is used to define the structure of an object and its properties. Type aliases are more flexible than interfaces, but they are less expressive, because they cannot describe the shape of an object in the same way that an interface can.

What is a module loader in TypeScript and how does it work?

View answer

Hide answer

A module loader in TypeScript is a mechanism for loading modules and their dependencies at runtime. It is responsible for resolving and loading modules, as well as managing their dependencies and ensuring that they are loaded in the correct order.

TypeScript supports several module loaders, including CommonJS, AMD, SystemJS, and ES6 modules. The choice of module loader depends on the platform and environment in which the code will be run.

The module loader is responsible for loading modules and their dependencies at runtime. When a module is imported, the module loader first checks if the module has already been loaded. If the module has not been loaded, the module loader loads the module and its dependencies, and then caches the result for future use.

Here's an example of importing a module in TypeScript:


import { add } from "./math";

const result = add(2, 3);

In the above example, we import the add function from a module called math. The module loader will first check if the math module has already been loaded. If it has not been loaded, the module loader will load the module and its dependencies, and then cache the result for future use.

The module loader is an important part of the TypeScript ecosystem, because it enables us to organize and reuse code in a modular and efficient way. It also provides a mechanism for managing dependencies and ensuring that they are loaded in the correct order.

What is a conditional type constraint in TypeScript and how is it used?

View answer

Hide answer

Conditional types in TypeScript are types that depend on a condition, evaluated at type-checking time, using the extends keyword. A conditional type constraint is a way of enforcing a certain type constraint based on a condition.

A common use case for conditional type constraints is to extract properties of an object that satisfy a certain condition. For example, given an object type T, we can extract the keys of T that have a value of type string with the following conditional type constraint:


type StringKeys<T> = {
  [K in keyof T]: T[K] extends string ? K : never
}[keyof T];

This type uses an indexed access type to extract the keys of T with a value of type string. It first maps each key K of T to K if T[K] is a string, and to never otherwise. Then it uses an indexed access type to get the union of all properties that were mapped to a non-never type.

Here's an example of using this type:

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

type PersonStringKeys = StringKeys<Person>; // "name" | "email"

In this example, PersonStringKeys is a union of the keys of Person with a value of type string.

What is the "infer" keyword in TypeScript and how is it used?

View answer

Hide answer

The infer keyword in TypeScript is used in conditional types to infer the type of a type parameter based on a type that depends on it. For example, we can use infer to extract the return type of a function type:


type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

In this example, the conditional type T extends (...args: any[]) => infer R ? R : never checks if T is a function type, and if it is, infers the return type R of that function type. Otherwise, it returns never.

Here's an example of using this type:


function add(a: number, b: number): number {
  return a + b;
}

type AddReturnType = ReturnType<typeof add>; // number

In this example, AddReturnType is inferred to be number, which is the return type of the add function.

How do you use the "exclude" and "extract" utility types in TypeScript?

View answer

Hide answer

The exclude and extract utility types in TypeScript are used to create new types that exclude or extract certain properties from a given type.

The exclude type is used to exclude properties that match a certain condition. For example, we can exclude all properties of a type T that have a value of type string with the following type:


type ExcludeString<T> = Pick<T, { [K in keyof T]: T[K] extends string ? never : K }[keyof T]>;

In this example, the Pick utility type is used to create a new type that only includes the properties of T that are not of type string. We do this by mapping each key K of T to never if T[K] is a string, and to K otherwise. Then we use an indexed access type to get the union of all properties that were mapped to K.

Here's an example of using this type:

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

type NonStringProps = ExcludeString<Person>; // { age: number }

In this example, NonStringProps is a new type that excludes the name and email properties of Person because they have a value of type string.

The extract type is used to extract properties that match a certain condition. For example, we can extract all properties of a type T that have a value of type string with the following type:


type ExtractString<T> = Pick<T, { [K in keyof T]: T[K] extends string ? K : never }[keyof T]>;

In this example, the Pick utility type is used to create a new type that only includes the properties of T that are of type string. We do this by mapping each key K of T to K if T[K] is a string, and to never otherwise. Then we use an indexed access type to get the union of all properties that were mapped to K.

Here's an example of using this type:


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

type StringProps = ExtractString<Person>; // { name: string, email: string }

In this example, StringProps is a new type that includes the name and email properties of Person because they have a value of type string.

What is a recursive type in TypeScript and how is it used

View answer

Hide answer

A recursive type in TypeScript is a type that refers to itself in its definition. Recursive types are useful for defining data structures that contain references to other instances of the same data structure, such as linked lists, trees, and graphs.

Here's an example of defining a recursive type for a binary tree:


type TreeNode<T> = {
  value: T;
  left: TreeNode<T> | null;
  right: TreeNode<T> | null;
};

In this example, the TreeNode type refers to itself in the definition of its left and right properties. This allows us to define binary trees that contain references to other binary trees.

Here's an example of using this type:


const tree: TreeNode<number> = {
  value: 1,
  left: {
    value: 2,
    left: { value: 4, left: null, right: null },
    right: null,
  },
  right: {
    value: 3,
    left: { value: 5, left: null, right: null },
    right: { value: 6, left: null, right: null },
  },
};

In this example, tree is a binary tree of numbers, with each node containing a value and references to its left and right child nodes.

What is a distributive conditional type in TypeScript and how is it used?

View answer

Hide answer

A distributive conditional type in TypeScript is a type that is applied to a union of types, and the condition is applied to each member of the union individually. This can be useful for creating new types that are based on a union of existing types.

Here's an example of defining a distributive conditional type:


type Filter<T, U> = T extends U ? T : never;

In this example, the Filter type takes two type parameters T and U. It applies a condition to T that checks whether T is assignable to U. If it is, then the type of T is returned. If not, then the never type is returned.

Here's an example of using this type:


type StringOrNumber = string | number;
type OnlyStrings = Filter<StringOrNumber, string>; // string

In this example, OnlyStrings is a new type that includes only the string type from the StringOrNumber union type.

When the Filter type is applied to a union of types, it distributes the condition over each member of the union, creating a new union of types that pass the condition. For example:


type StringOrNumberArray = (string | number)[];
type OnlyStringsArray = Filter<StringOrNumberArray, string[]>; // string[]

In this example, OnlyStringsArray is a new type that includes only arrays of string from the StringOrNumberArray union type.

What is the "type" keyword in TypeScript and how is it used?

View answer

Hide answer

The type keyword in TypeScript is used to define a new type alias. Type aliases are used to give a name to a complex type, or to create a union of existing types. They can also be used to make types more readable and easier to understand.

Here's an example of defining a type alias:


type Person = {
  name: string;
  age: number;
  email: string;
};

In this example, Person is a new type alias that defines a type with three properties: name, age, and email.

Type aliases can also be used to create a union of existing types. For example:


type StringOrNumber = string | number;

In this example, StringOrNumber is a new type alias that defines a union type of string and number.

What is the "import type" statement in TypeScript and how is it used?

View answer

Hide answer

The import type statement in TypeScript is used to import a type definition from a module without importing the module itself. This is useful when you only need the type information of a module, and not its runtime behavior.

Here's an example of using the import type statement:


import type { Person } from './person';

function sayHello(person: Person) {
  console.log(`Hello, ${person.name}!`);
}

In this example, the Person type is imported from the ./person module using the import type statement. This allows us to use the Person type in the sayHello function without importing the entire ./person module.

Note that the import type statement only imports the type information of a module, and not its runtime behavior. If you need to use the runtime behavior of a module, you should use the regular import statement.

What is the "const" assertion in TypeScript and how is it used?

View answer

Hide answer

The const assertion in TypeScript is used to tell the compiler that a value will never change. This can be used to create immutable values, which can improve the readability and maintainability of code.

Here's an example of using the const assertion:


const person = {
  name: 'John',
  age: 30,
} as const;

person.name = 'Jane'; // Error: Cannot assign to 'name' because it is a read-only property.

In this example, the const assertion is used to create an immutable object named person. Because of the const assertion, TypeScript knows that the properties of person should never be changed after it is created. This allows TypeScript to prevent us from accidentally modifying the object.

How do you use the "readonly" utility type in TypeScript?

View answer

Hide answer

The readonly utility type in TypeScript is used to make all properties of an object read-only. This can be useful when you want to ensure that an object is not modified after it is created.

Here's an example of using the readonly utility type:


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

const person: Person = {
  name: 'John',
  age: 30,
};

person.name = 'Jane'; // Error: Cannot assign to 'name' because it is a read-only property.

In this example, the readonly modifier is used to make the name and age properties of the Person interface read-only. The person object is then created using the Person interface, and because of the readonly modifier, the name property cannot be modified.

Note that the readonly modifier only makes the properties read-only on the surface level. If the properties of the object are themselves mutable objects, those objects can still be modified. If you need to make the properties of the object deeply immutable, you can use a library like Immutable.js.

What is the "Partial" type in TypeScript and how is it used?

View answer

Hide answer

The Partial type in TypeScript is a built-in utility type that makes all properties of an object optional. This can be useful when you want to create a new object based on an existing object, but with some properties modified.

Here's an example of using the Partial type:


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

function updatePerson(person: Person, updates: Partial<Person>): Person {
  return { ...person, ...updates };
}

const person: Person = { name: 'John', age: 30, email: '[email protected]' };

const updatedPerson = updatePerson(person, { age: 31 });

console.log(updatedPerson); // { name: 'John', age: 31, email: '[email protected]' 

In this example, the Partial type is used to make all properties of the Person interface optional. The updatePerson function then takes a person object and an updates object, which can have some or all of the properties of a Person object. The function then returns a new object with the properties of the original person object merged with the properties of the updates object.

Note that the Partial type only makes the properties optional on the surface level. If the properties of the object are themselves complex objects, you may need to use the Partial type recursively or use a library like Immutable.js to create a deeply partial object.

Other Interview Questions

ReactJS

Business Analyst

Android

Javascript

Power BI Django .NET Core
Drupal TestNG C#
React Native SAS Kubernetes
Check Other Interview Questions
customers across world
Join 1200+ companies in 75+ countries.
Try the most candidate friendly skills assessment tool today.
GET STARTED FOR FREE
g2 badges
logo
40 min tests.
No trick questions.
Accurate shortlisting.

[email protected]

Product
  • Product Tour
  • Pricing
  • Features
  • Integrations
Usecases
  • Aptitude Tests
  • Coding Tests
  • Psychometric Tests
  • Personality Tests
Helpful Content
  • 52 pre-employment tools compared
  • Compare Adaface
  • Compare Codility vs Adaface
  • Compare HackerRank vs Adaface
  • Compare Mettl vs Adaface
BOOKS & TOOLS
  • Guide to pre-employment tests
  • Check out all tools
Company
  • About Us
  • Join Us
  • Blog
Locations
  • Singapore (HQ)

    32 Carpenter Street, Singapore 059911

    Contact: +65 9447 0488

  • India

    WeWork Prestige Atlanta, 80 Feet Main Road, Koramangala 1A Block, Bengaluru, Karnataka, 560034

    Contact: +91 6305713227

© 2022 Adaface Pte. Ltd.
Terms Privacy Trust Guide

🌎 Pick your language

English Norsk Dansk Deutsche Nederlands Svenska Français Español Chinese (简体中文) Italiano Japanese (日本語) Polskie Português Russian (русский)
Search 500+ tests by skill or role name
JavaScript
React
How many questions will be there in AWS test?
What test do you recommend for analysts?