Class decorators

Class decorators allow us to augment a class or perform operations over any of its members, and the decorator statement is executed before the class gets instanced.

Creating a class decorator just requires defining a plain function, whose signature is a pointer to the constructor belonging to the class we want to decorate, typed as function (or any other type that inherits from the function). The formal declaration defines a ClassDecorator, as follows:

declare type ClassDecorator = <TFunction extends Function>(Target: TFunction) => TFunction | void;

Yes, it is really difficult to grasp what this gibberish means, right? Let's put everything in context through a simple example, like this:

function Banana(target: Function): void {
target.prototype.banana = function(): void {
console.log('We have bananas!');
}
}

@Banana
class FruitBasket {
constructor() {
// Implementation goes here...
}
}
var basket = new FruitBasket();
basket.banana(); // console will output 'We have bananas!'

As we can see, we have gained a banana() method that was not originally defined in the FruitBasket class just by properly decorating it with the Banana decorator. It is worth mentioning though that this won't actually compile. The compiler will complain that FruitBasket does not have a banana() method, and rightfully so. TypeScript is typed. In ES5, we could do anything we wanted and any wrong doing would be discovered in runtime. So at this point, we need to tell the compiler that this is OK. So, how do we do that? One way is that when we create our basket instance, we give it the type any like so:

var basket: any = new FruitBasket();
basket.banana();

What we did here is actively give the variable basket the any type and thereby fight the TypeScript compilers urge to infer the type to be FruitBasket. By being of type any TypeScript has no idea of knowing whether what we have done to it is correct or not. Another way of essentially accomplishing the same effect is to type like this instead:

var basket = new FruitBasket();
(basket as any).banana();

Here, we are doing a conversion on the fly with the as-operator and thereby we tell the compiler that this is OK.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset