How to Check the Object Type on Runtime in TypeScript
- Main Types in TypeScript
- Check the Class Type on Runtime in TypeScript
- Check the Interface Type on Runtime in TypeScript
This article discusses how to check the object type on runtime in TypeScript.
Main Types in TypeScript
TypeScript is a strongly typed language. Therefore, it checks for the types in compile time, which reduces runtime errors.
In TypeScript, we have several main types, as shown in the following.
- Primitive types such as string, number, and boolean
- Custom class types
- Interface types
- Union types
- Type aliases
Check the Class Type on Runtime in TypeScript
TypeScript supports the class
keyword from the EcmaScript 6. It can be used to write your code in an OOP way.
Let’s create the class Engineer
.
class Engineer {
}
Let’s add a method since this class doesn’t contain any properties or behaviors.
class Engineer {
visitSite(): void {
console.log("This is the Engineer class");
}
}
Let’s say we got another class, Doctor
, as shown in the following.
class Doctor {
visitWard(): void {
console.log("This is the Doctor class");
}
}
The Engineer
and Doctor
are two user-defined types. In some scenarios, we must check whether an existing object type belongs to the Engineer
or Doctor
class.
This is quite straightforward with the TypeScript instanceof
operator.
Use the instanceof
Operator to Check the Class Type
It checks whether the given object is an instance of a TypeScript class or a constructor. It considers the multi-level inheritance to check whether the relevant class appears at a different level.
If a matching class is found, it will return true
; otherwise, it will output false
.
Syntax:
my_object instanceof my_custom_class_type
Let’s use this operator to differentiate between Engineer
and Doctor
classes inside our TypeScript logic.
First, we will create a new checker function checkObjectType()
.
function checkObjectType(myObject) {
if (myObject instanceof Engineer) {
myObject.visitSite()
}
if (myObject instanceof Doctor) {
myObject.visitWard()
}
}
In the above checker function, we check the myObject
’s class. Based on the result, we call the belonged class methods visitSite()
or visitWard()
.
Let’s initiate objects from both the classes and pass the object to the checkObjectType
method.
let engineerObject: Engineer = new Engineer;
let doctorObject: Doctor = new Doctor;
checkObjectType(engineerObject);
checkObjectType(doctorObject);
Output:
As expected, TypeScript identifies the correct class for each object provided.
Check the Interface Type on Runtime in TypeScript
The instanceof
can be used to check whether the given instance belongs to a class. But, this doesn’t work with TypeScript interface types or type aliases.
In runtime, all these interface types are gone. Hence, the usual JavaScript typeof
operator will give the output as the object
.
Let’s define two interfaces, Airplane
and Car
, as shown in the following.
interface Airplane {
hasWings() {
console.log("2 wings");
}
}
interface Car {
hasWheels() {
console.log("4 wheels");
}
}
Next, we will be creating a TypeScript user-defined type guard to check whether the given object belongs to the Airplane
or Car
type and narrow the object to a compatible type. Here, we should use type predicate as the return type.
Syntax of the type predicate:
my_parameter_name is custom_type
The my_parameter_name
should be the current argument passed to the function. In this case, the custom_type
will be the Airplane
or Car
.
Let’s define the two type guards:
function isAirplane(anyObject: any): anyObject is Airplane {
return (anyObject as Airplane).hasWings() !=== undefined;
}
We check the shape of the object is equivalent to the interface shape by checking whether the hasWings()
method is available to the passed object anyObject
. Then, we return the type predicate that narrows the object to the Airplane
type.
We can implement the isCar()
function similarly.
function isCar(anyObject: any): anyObject is Car {
return (anyObject as Car).hasWheels() !=== undefined;
}
Finally, we can implement the testType()
function to test the code.
let car: Car = {wheels: 4};
let flight: Airplane = {wings: 2};
function testType(obj: any) {
if (isAirplane(obj)) {
// 'obj' is narrowed to type 'Airplane'
console.log("Airplane wings: "+ obj.wings);
}
else if (isCar(obj)) {
// 'obj' is narrowed to type 'Car'
console.log("Car wheels: "+ obj.wheels);
}
}
testType(car);
testType(flight);
Output:
With the help of user-defined type guards, we can check the exact type for interfaces at runtime.
Nimesha is a Full-stack Software Engineer for more than five years, he loves technology, as technology has the power to solve our many problems within just a minute. He have been contributing to various projects over the last 5+ years and working with almost all the so-called 03 tiers(DB, M-Tier, and Client). Recently, he has started working with DevOps technologies such as Azure administration, Kubernetes, Terraform automation, and Bash scripting as well.