Frequently asked - TypeScript Interview Questions and Answers - Part 01
1. What is TypeScript? Why should we use it?
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript which runs on any browser or JavaScript engine.
TypeScript offers support for the latest JavaScript features and also has some additional features like static typing, object oriented programming and automatic assignment of constructor.
2. What are Types in TypeScript?
The type represents the type of the value we are using in our programs. TypeScript supports simplest units of data such as numbers, strings, boolean as well as additional types like enum, any, never.
In TypeScript, we are declaring a variable with its type explicitly by appending the :
with the variable name followed by the type.
let decimal: number = 6;
let color: string = "blue";
let notSure: any = 4;
let unusable: void = undefined;
The reason adding types are:
- Types have proven ability to enhance code quality and understandability.
- It’s better for the compiler to catch errors than to have things fail at runtime.
- Types are one of the best forms of documentation we can have.
3. What is Type assertions in TypeScript?
A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data. It has no runtime impact, and is used purely by the compiler. TypeScript assumes that we have performed any special checks that we need.
let strLength: number = (<string>someString).length;
4. What is as
syntax in TypeScript?
The as
is additional syntax for Type assertion in TypeScript. The reason for introducing the as
-syntax is that the original syntax (<type>
) conflicted with JSX.
let strLength: number = (someString as string).length;
When using TypeScript with JSX
, only as
-style assertions are allowed.
5. What is Compilation Context?
The compilation context is basically grouping of the files that TypeScript will parse and analyze to determine what is valid and what isn’t. Along with the information about which files, the compilation context contains information about which compiler options. A great way to define this logical grouping is using a tsconfig.json
file.
A tsconfig.json
might look like the following snippet:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"sourceMap": true,
"outFile": "./",
"rootDir": "./",
}
}
6. What is an Interface in TypeScript?
An interface
is a virtual structure that only exists within the context of TypeScript. The TypeScript compiler uses interfaces solely for type-checking purposes. Once your code is transpiled to its target language, it will be stripped from its interfaces - JavaScript isn’t typed, there’s no use for them there.
Also, an interface
is simply a structural contract that defines what the properties of an object should have as a name and as a type. How you implement or initialise the properties declared within the interface is not relevant to it.
interface Car {
modelName: string;
year: number;
}
class CarMaker {
static create(event: Car) {
return { modelName: event.name, year: event.year };
}
}
The CarMaker.create()
returns an object that surely looks like a Car
would! It has the modelName
as string and year
as number.”
7. What is optional properties?
Sometimes, not all properties of an interface may be required. Some exist under certain conditions or may not be there at all. These optional properties are popular when creating patterns like “option bags” where you pass an object to a function that only has a couple of properties filled in.
In TypeScript, interfaces with optional properties are written similar to other interfaces, with each optional property denoted by a ?
at the end of the property name in the declaration.
interface Car {
modelName: string;
year: number;
isAC?: boolean;
}
function CarMaker(config: Car): Car {
let newCar = { name: config.modelName, year: config.year };
if(config.isAC) {
newCar.isAC = true;
}
return newCar;
}
8. What is readonly
? How it differ from const
?
When we want some properties of an object should only be modifiable when the object is created, we can use readonly
modifier.
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
Now we will get error if we try to modify x
or y
in p1
.
The difference between readonly
and const
is: const
is used on a variable whereas readonly
is used on properties of an object.”
9. Can an interface
extends a class
just like a class
implements interface
?
Yes, an interface
extends a class
, when it does it inherits the members of the class but not their implementations. Interfaces inherit even the private and protected members of a base class. This means that when you create an interface that extends a class with private or protected members, that interface type can only be implemented by that class or a subclass of it.
10. How to use class
and inheritance
?
A class
can be seen as a blueprint of an object. Traditional JavaScript uses functions and prototype-based inheritance to build objects. In TypeScript, we can use object-oriented class-based approach.
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
add(point: Point) {
return new Point(this.x + point.x, this.y + point.y);
}
}
var p1 = new Point(0, 10);
TypeScript supports single inheritance using the extends
keyword.
class Point3D extends Point {
z: number;
constructor(x: number, y: number, z: number) {
super(x, y);
this.z = z;
}
add(point: Point3D) {
var point2D = super.add(point);
return new Point3D(point2D.x, point2D.y, this.z + point.z);
}
}
If we have a constructor in your class then we must call the parent constructor from your constructor (TypeScript will point this out). This ensures that the stuff that it needs to set on this gets set. Followed by the call to super
we can add any additional stuff we want to do in your constructor (here we add another member z
).
Note that we override parent member functions easily (here we override add) and still use the functionality of the super class in your members (using super.
syntax).
11. What is static
properties?
TypeScript classes support static
properties that are shared by all instances of the class. A natural place to put (and access) them is on the class itself.
class Something {
static instances = 0;
constructor() {
Something.instances++;
}
}
var s1 = new Something();
console.log(Something.instances); // 2
We can have static members as well as static functions.
12. What are all the other access modifiers that TypeScript supports?
TypeScript supports access modifiers public
, private
and protected
which determine the accessibility of a class
member as given below:
public
- All the members of the class, its child classes, and the instance of the class can access.protected
- All the members of the class and its child classes can access them. But the instance of the class can not access.private
- Only the members of the class can access them., If an access modifier is not specified it is implicitlypublic
as that matches the convenient nature of JavaScript.
Also note that at runtime (in the generated JS) these have no significance but will give you compile time errors if you use them incorrectly.
13. What is abstract
class?
Abstract
can be thought of as an access modifier. Abstract
classes are base classes from which other classes may be derived. They may not be instantiated directly. Unlike an interface, an abstract class may contain implementation details for its members. The abstract
keyword is used to define abstract classes as well as abstract methods within an abstract class.
Having an abstract
modifier primarily means that such functionality cannot be directly invoked and a child class must provide the functionality.
abstract
classes cannot be directly instantiated. Instead the user must create some class that inherits from theabstract class
.abstract
members cannot be directly accessed and a child class must provide the functionality.,
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log("An animal");
}
}
14. How to write typed functions in TypeScript?
TypeScript functions can be created both as a named function or as an anonymous function. We can add types to each of the parameters and then to the function itself to add a return type. TypeScript can figure the return type out by looking at the return statements.
// Named function
function add(x: number, y: number): number {
return x + y;
}
// Anonymous function
let myAdd = function(x: number, y: number): number { return x + y; };
If we want to write full type of the function:
let myAdd: (x: number, y: number) => number =
function(x: number, y: number): number { return x + y; };
15. What is Contextual typing?
TypeScript compiler can figure out the type if you have types on one side of the equation but not the other. For example, we can re-write the previous example function as follow:
let myAdd: (baseValue: number, increment: number) => number =
function(x, y) { return x + y; };
Note that we can omit the typings on the right side of the equal since it can be figured out automatically by TypeScript. This helps cut down on the amount of effort to keep our program typed.
16. What is Optional and Default parameters?
In JavaScript, every parameter of a function is optional, and users may leave them off as they see fit. When they do, their value is undefined
. We can get this functionality in TypeScript by adding a ?
to the end of parameters we want to be optional. For example:
function greeting(firstName: string, lastName?: string) {
if(lastName) {
return "Hello! " + firstName + " " + lastName;
} else {
return "Hello! " + firstName;
}
}
In TypeScript, we can also set a value that a parameter will be assigned if the user does not provide one, or if the user passes undefined
in its place. For example, consider the same above example:
function greeting(firstName: string, lastName = "Dude") {
return "Hello! " + firstName + " " + lastName;}
17. What is Rest parameters?
Sometimes, we want to work with multiple parameters as a group, or we may not know how many parameters a function will ultimately take. In JavaScript, we can work with the arguments
directly using the arguments variable that is visible inside every function body. In TypeScript, you can gather these arguments together into a variable:
function greeting(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
let greetText = greeting("John", "Doe", "Bruce", "Wayne");
Rest parameters are treated as a boundless number of optional parameters. When passing arguments for a rest parameter, we can use as many as we want; we can even pass none. The compiler will build an array of the arguments passed in with the name given after the ellipsis (...
), allowing us to use it in our function.
18. What is Generics in TypeScript?
Consider the below function where we are unsure about the parameter:
function identity(arg: any): any {
return arg;
}
While using any
is certainly generic in that it will cause the function to accept any and all types for the type of arg
, we actually are losing the information about what that type was when the function returns. If we need to capture the type of the argument to determine which type is being returned, we will use a special kind of type variable.
function identity<T>(arg: T): T {
return arg;
}
We’ve now added a type variable T
to the identity function. This T
allows us to capture the type the user provides (e.g. number
), so that we can use that information later. Here, we use T
again as the return type. On inspection, we can now see the same type is used for the argument and the return type. This allows us to traffic that type information in one side of the function and out the other. We say that this version of the identity
function is generic, as it works over a range of types.
19. What is Generic Class?
A generic class has a similar shape to a generic interface. Generic classes have a generic type parameter list in angle brackets (<>
) following the name of the class.
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
20. What is Enum
?
Enum
are a TypeScipt data type that allow the organization of number-based collections of unique identifiers.
enum Gender {
Male,
Female
Other
}
console.log(Gender.Female); // 1
We can also access an enum value by it’s number value.
console.log(Gender[1]); // Female
Enums are zero-based, but we can change that by setting a number value of our choice on the first item. Here for example our enum will have an index that starts with 1:
enum Gender {
Male = 1,
Female
Other
}
console.log(Gender.Female); // 2