TypeScript is an open-source superset of JavaScript developed by Microsoft to add additional features without breaking existing programs. TypeScript is now widely used by front-end and full-stack developers for large-scale projects due to its unique benefits like static typing and many shorthand notations.
Today, we’ll help you prepare for your TypeScript coding interview by covering 50 of the top TypeScript interview questions and answers.
Here’s what we’ll cover today:
Number type: It is used to represent number type values. All the numbers in TypeScript are stored as floating-point values.
let identifier: number = value;
String type: It represents a sequence of characters stored as Unicode UTF-16 code. Strings are enclosed in single or double quotation marks.
let identifier: string = " ";
Boolean type: a logical binary switch that holds either true or false
let identifier: bool = Boolean value;
Null type: Null represents a variable whose value is undefined.
let num: number = null;
Undefined type: an undefined literal that is the starting point of all variables.
let num: number = undefined;
Void type: The type assigned to methods that have no return value.
let unusable: void = undefined;
The current stable version is 4.2.3.
Interfaces define a contract or structure for objects that use that interface.
An interface is defined with the keyword interface and it can include properties and method declarations using a function or an arrow function.
interface IEmployee {
empCode: number;
empName: string;
getSalary: (number) => number; // arrow function
getManagerName(number): string;
}
Modules in TypeScript are a collection of related variables, functions, classes, and interfaces.
You can think of modules as containers that contain everything needed to execute a task. Modules can be imported to easily share code between projects.
module module_name{
class xyz{
export sum(x, y){
return x+y;
}
}
You can use Node.js with TypeScript to bring the benefits of TypeScript to backend work.
Simply install the TypeScript compiler into your Node.js by entering the following command:
npm i -g typescript
Type assertion in TypeScript works like typecasting in other languages but without the type checking or restructuring of data possible in languages like C# and Java. Type assertion has no impact on runtime and is used purely by the compiler.
Type assertion is essentially a soft version of typecasting that suggests the compiler see the variable as a certain type but does not force it into that mold if it’s in a different form.
You can create variables in three ways: var, let, and const.
var is the old style of fiercely scoped variables. You should avoid using var whenever possible because it can cause issues in larger projects.
var num:number = 1;
let is the default way of declaring variables in TypeScript, Compared to var, let reduces the number of compile-time errors and increases code readability.
let num:number = 1;
const creates a constant variable whose value cannot change. It uses the same scoping rules as let and helps reduce overall program complexity.
const num:number = 100;
You can use the super() function to call the constructor of the base class.
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) {
super(name);
}
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
Mixins are essentially inheritance that works in the opposite direction. Mixins allow you to build new classes by combining simpler partial class setups from previous classes.
Instead of class A extending class B to gain its functionality, class B takes from class A and returns a new class with additional functionality.
You can either use a juggle-check, which checks both null and undefined, and strict-check which returns true for values set to null and won’t evaluate true for undefined variables.
//juggle
if (x == null) {
}
var a: number;
var b: number = null;
function check(x, name) {
if (x == null) {
console.log(name + ' == null');
}
if (x === null) {
console.log(name + ' === null');
}
if (typeof x === 'undefined') {
console.log(name + ' is undefined');
}
}
check(a, 'a');
check(b, 'b');
Getters and setters are special types of methods that help you delegate different levels of access to private variables based on the needs of the program.
Getters allow you to reference a value but cannot edit it. Setters allow you to change the value of a variable but not see its current value. These are essential to achieve encapsulation.
For example, a new employer may be able to get the number of employees in the company but does not have permission to set the number of employees.
const fullNameMaxLength = 10;
class Employee {
private _fullName: string = "";
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (newName && newName.length > fullNameMaxLength) {
throw new Error("fullName has a max length of " + fullNameMaxLength);
}
this._fullName = newName;
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
console.log(employee.fullName);
}
You can use the export keyword to open modules up for use outside the module.
module Admin {
// use the export keyword in TypeScript to access the class outside
export class Employee {
constructor(name: string, email: string) { }
}
let alex = new Employee('alex', 'alex@gmail.com');
}
// The Admin variable will allow you to access the Employee class outside the module with the help of the export keyword in TypeScript
let nick = new Admin.Employee('nick', 'nick@yahoo.com');
Similar to JavaScript, You can use the parseInt or parseFloat functions to convert a string to an integer or float, respectively. You can also use the unary operator + to convert a string to the most fitting numeric type, “3” becomes the integer 3 while “3.14” becomes the float 3.14.
var x = "32";
var y: number = +x;
A map file is a source map that shows how the original TypeScript code was interpreted into usable JavaScript code. They help simplify debugging because you can catch any odd compiler behavior.
Debugging tools can also use these files to allow you to edit the underlying TypeScript rather than the emitted JavaScript file.
Classes represent the shared behaviors and attributes of a group of related objects.
For example, our class might be Student which all have the attendClass method. On the other hand, John is an individual instance of type Student and may have additional unique behaviors like attendExtracurricular.
You declare classes using the keyword class:
class Student {
studCode: number;
studName: string;
constructor(code: number, name: string) {
this.studName = name;
this.studCode = code;
}
TypeScript is an open-source syntactic superset of JavaScript that compiles to JavaScript. All original JavaScript libraries and syntax still works but TypeScript adds additional syntax options and compiler features not found in JavaScript.
TypeScript can also interface with most of the same technologies as JavaScript, such as Angular and jQuery.
JSX is an embeddable XML-like syntax that allows you to create HTML. TypeScript supports embedding, type checking, and compiling JSX directly to JavaScript.
TypeScript has built-in support for preserve, react, and react-native.
preserve keeps the JSX intact for use in a subsequent transformation.react does not go through a JSX transformation and instead emits react.createElement and outputs as a .js file extension.react-native combines preserve and react in that it maintains all JSX and outputs as a .js extension.You need to call the TypeScript compiler tsc to compile a file. You’ll need to have the TypeScript compiler installed, which you can do using npm.
npm install -g typescript
tsc <TypeScript File Name>
Fat arrow function is a shorthand syntax for defining function expressions of anonymous functions. It’s similar to lambda functions in other languages. The arrow function lets you skip the function keyword and write more concise code.
Rest parameters allow you to pass a varied number of arguments (zero or more) to a function. This is useful when you’re unsure how many parameters a function will receive. All arguments after the rest symbol ... will be stored in an array.
For example:
function Greet(greeting: string, ...names: string[]) {
return greeting + " " + names.join(", ") + "!";
}
Greet("Hello", "Steve", "Bill"); // returns "Hello Steve, Bill!"
Greet("Hello");// returns "Hello !"
The rest parameter must be the last on parameter definition and you can only have 1 rest parameter per function.
Triple-slash Directives are single-line comments that contain an XML tag to use as compiler directives. Each directive signals what to load during the compilation process. Triple-slash Directives only work at the top of their file and will be treated as normal comments anywhere else in the file.
/// <reference path="..." /> is the most common directive and defines the dependency between files./// <reference types="..." /> is similar to path but defines a dependency for a package./// <reference lib="..." /> allows you to explicitly include the built-in lib file.Omit is a form of utility type, which facilitates common type transformations. Omit lets you construct a type by passing a current Type and selecting Keys to be omitted in the new type.
Omit<Type, Keys>
For example:
interface Todo {
title: string;
description: string;
completed: boolean;
createdAt: number;
}
type TodoPreview = Omit<Todo, "description">;
To overload, a function in TypeScript, simply create two functions of the same name but have different argument/return types. Both functions must accept the same number of arguments. This is an essential part of polymorphism in TypeScript.
For example, you could make an add function that sums the two arguments if they’re numbers and concatenates them if they’re strings.
function add(a:string, b:string):string;
function add(a:number, b:number): number;
function add(a: any, b:any): any {
return a + b;
}
add("Hello ", "Steve"); // returns "Hello Steve"
add(10, 20); // returns 30
You can use the partial mapped type to easily make all properties optional.
You should use unknown if you don’t know which type to expect upfront but want to assign it later on, and the any keyword will not work.
A decorator is a special kind of declaration that lets you modify classes or class members all at once by marking them with the @<name> annotation. Each decorator must refer to a function that’ll be evaluated at runtime.
For example, the decorator @sealed would correspond to the sealed function. Anything marked with @sealed would be used to evaluate the sealed function.
function sealed(target) {
// do something with 'target' ...
}
They can be attached to:
Decorators are not enabled by default. To enable them, you have to edit the
experimentalDecoratorsfield in the compiler options from yourtsconfig.jsonfile or the command line.
declare keyword?enum collection?Record type used for?Ambients in TypeScript and when should you use them?Both interface and type let you describe the shape of an object, but they serve slightly different purposes.
Interfaces can be merged and extended multiple times. They’re great for defining object contracts in libraries or APIs.
Types are more flexible. You can use them for unions, intersections, and more complex type compositions, but they can’t be reopened once defined.
Example:
interface User { name: string }interface User { age: number } // merged automaticallytype Point = { x: number } & { y: number } // combined manually
When to use which:
Use interface for defining contracts.
Use type for creating combinations, unions, and mapped types.
Template literal types let you build string types dynamically using other types. They’re powerful for creating literal unions that follow a pattern.
Example:
type HttpMethod = 'get' | 'post' | 'put';type Endpoint<M extends string> = `${M}/api`;type ApiPaths = Endpoint<HttpMethod>;// Results: "get/api" | "post/api" | "put/api"
Template literal types are especially useful when defining type-safe API routes, event names, or CSS class name conventions.
Introduced in TypeScript 4.9, the satisfies operator ensures that a value meets the requirements of a type without changing the inferred type of the value.
Example:
type Colors = 'red' | 'blue';const theme = {primary: 'red',secondary: 'blue',} satisfies Record<string, Colors>;
If you tried to assign 'green', the compiler would throw an error.
Unlike as, satisfies preserves the exact literal types and avoids unwanted widening (e.g., turning 'red' into string).
Using as const makes your object or array readonly and locks in its literal types.
Example:
const directions = ['north', 'south', 'east', 'west'] as const;// directions: readonly ["north", "south", "east", "west"]type Direction = typeof directions[number];// "north" | "south" | "east" | "west"
It’s commonly used when defining configuration objects, Redux actions, or constant sets of keys.
TypeScript automatically narrows variable types when it detects certain conditions. You can guide this process using:
typeof – checks primitive types.
instanceof – checks class instances.
in – checks for property existence.
Equality checks – discriminate between union members.
Example:
function printValue(value: string | number) {if (typeof value === 'string') console.log(value.toUpperCase());else console.log(value.toFixed(2));}
Type narrowing is one of the most powerful ways TypeScript improves safety without adding runtime overhead.
Preparing for interviews is always stressful, but proper preparation beforehand can help you build confidence. When preparing for your interview, remember to:
To help you get more hands-on practice with TypeScript, Educative has created the TypeScript for Front-End Developers Path. This Path is full of our best TypeScript content from across our site. You’ll revise the fundamentals, explore practical applications, and build React projects all using Educative’s in-browser coding environments.
By the end of the Path, you’ll have the skills you need to ace your next TypeScript interview.