As you probably know when you subscribe to an observable or event in JavaScript, you usually need to unsubscribe at a certain point to release memory in the system. Otherwise, you will have a memory leak.

A memory leak occurs when a section of memory that is no longer being used is still being occupied needlessly instead of being returned to the OS

In Angular components or directives, you will unsubscribe inside the ngOnDestroy lifecycle hook.

For example, if you have a component with three subscriptions:

You need to create the ngOnDestroy method and unsubscribe from each.

OK, that’s nice, but I want to automate the unsubscribe process. What if we could create a class decorator that will do the work for us? Maybe something like this:

Let’s create a class decorator named AutoUnsubscribe to clean our code.

In typescript or babel , a class decorator is just a function that takes one parameter, the constructor of the decorated class.

The class decorator is applied to the constructor of the class and can be used to observe, modify, or replace a class definition.

🤓 There are three simple steps here:

Save a reference to the original ngOnDestroy function. Create our version of ngOnDestroy , loop over the class properties and invoke the unsubscribe() function if it exists. Invoke the original ngOnDestroy function if it exists.

That’s all, piece of 🍰.

😁 But…

But wait a minute, what if for some crazy reason you need to exclude subscriptions? for example you don’t want to unsubscribe from the $two subscription when the component is destroyed.

In this case we need to pass an argument to our decorator ( an array of excluded properties ), so we need to use a Decorator Factory:

A Decorator Factory is simply a function that returns the expression that will be called by the decorator at runtime.

We are just checking that the property name is not in the blacklist array before invoking the unsubscribe() function.

Now we can use our decorator like this:

😃 Now we are done!

You can find the decorator here. If you have further improvements, please make a pull request.