I will assume that you have already read all the previous posts of these series.

In the previous post in this series we learned what are decorators and how they are implemented in TypeScript. We know how to work with class, method, property and parameter decorators, how to create a decorator factory and how to use a decorator factory to implement configurable decorators.

In this post we will learn about:

1. Why we need reflection in JavaScript?

2. The metadata reflection API

3. Basic type serialization

4. Complex type serialization

Let’s start by learning why we need reflection in JavaScript.

1. Why we need reflection in JavaScript?

The name reflection is used to describe code which is able to inspect other code in the same system (or itself).

Reflection is useful for a number of use cases (Composition/Dependency Injection, Run-time Type Assertions, Testing).

Our JavaScript applications are getting bigger and bigger and we are starting to need some tools (like inversion of control containers) and features like (run-time type assertions) to manage this increasing complexity. The problem is that because there is not reflection in JavaScript some of this tools and features cannot be implemented, or at least they can not be implemented to be as powerful as they are in programming languages like C# or Java.

A powerful reflection API should allow us to examine an unknown object at run-time and find out everything about it. We should be able to find things like:

C) Obtaining return type metadata using the reflect metadata API

We can also get information about the return type of a method using the "design:returntype" metadata key:

Reflect.getMetadata("design:returntype", target, key);

3. Basic type serialization

Let’s take a look to the "design:paramtypes" example above again. Notice the that interfaces IFoo and object literal { test : string} are serialized as Object. This is because TypeScript only supports basic type serialization. The basic type serialization rules are:

number serialized as Number

string serialized as String

boolean serialized as Boolean

any serialized as Object

void serializes as undefined

Array serialized as Array

If a Tuple, serialized as Array

If a class serialized it as the class constructor

If an Enum serialized it as Number

If has at least one call signature, serialized as Function

Otherwise serialized as Object (Including interfaces)

Interfaces and object literals may be serialize in the future via complex type serialization but this feature is not available at this time.

4. Complex types serialization

The TypeScript team is working on a proposal that will allow us to generate metadata for complex types.

They proposal describes how some complex types will be serialized. The serialization rules above will still be used for basic type but a different serialization logic will be used for complex types. In the proposal there is a base type that is used to describe all the possible types:

We can also find the classes that will be used to describe each of the possible types. For example, we can find the class proposed to be used to serialize genetic interfaces interface foo<bar> { /* ... */}:

As we can see above there will be an attribute which indicates the implemented interfaces:

/**
* Implemented interfaces.
*/
implements?: Type[];

That information could be used to do things like validate if an entity implements certain interface at run-time, which could be really useful for an IoC container.

We don’t know when complex type serialization support will be added to TypeScript but we cannot wait because we have plans to use it to add some cool features to our awesome IoC container for JavaScript: InversifyJS.

5. Conclusion

In this series we have learned in-depth 4 out of the 4 available types of decorators, how to create a decorator factory and how to use a decorator factory to implement configurable decorators.

We also know how to work with the metadata reflection API.

We will keep this blog updated and write more about the metadata reflection API in the future. Don’t forget to subscribe if you don’t want to miss it out!