Object-oriented decorator using simple factory function and closures

Chris
Chris’ Dialogue
Published in
3 min readMar 9, 2019

Lately I have seen that TypeScript introduce decorator.

It works like this:

function f() {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("f(): called");
}
}

function g() {
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("g(): called");
}
}

class C {
@f()
@g()
method() {}
}

Which would print this output to the console:

g(): called
f(): called

I am anti-fan of using traditional object-oriented approach in TypeScript and Javascript.

The reason is simple: Higher-order function and Closures already provide simpler yet more powerful concept to handle these cases.

I believe decorator pattern can be achieved using higher-order function and closures.

For example: This decorator pattern can be written in this way using only function.

function f (sourceObject: C): C {
console.log("f(): called");
return sourceObject
}
function g (sourceObject: C): C {
console.log("g(): called");
return sourceObject
}
function createObjectOfTypeC () { // This is called factory function
const result = new C();
return g(f(c))
}

Let’s take a look at real-world example

In MVC.net, we use decorator to ensure authorisation for endpoint

This will make sure that before user can call endpoint “Hello”, user must have authorized session.

We can use closures and higher order function in TypeScript to achieve same result.

We achieved the exactly same thing, which just only one more line of }); to type into code.

I prefer closures and higher-order function than decorator for many reasons.

The most important: Less concept to learn for developers. If you use decorator, you need to know about decorator interface, property descriptor, reflection, etc. While with higher-order function and closures, it is a concept that is already well-known to TypeScript developers (I presumed).

Also, closures and higher-order function are used in many occasions. Probability of any random TypeScript developer know about closures and how it works would be high. Any TypeScript developer, or even just Javascript developer who happened to jump into codebase would be able to understand the code without a need to looking up what decorator do and what kind of interfaces and parameters TypeScript provided.

Also, it is more flexible. If you use decorator and you need something more than what interfaces provided (target: any, propertyKey: string, descriptor: PropertyDescriptor) you are stuck.

We can do so many things with Closures and Higher-order function.

I believe some syntax for traditional Object-oriented language such as decorator was born because in that era, those languages did not have concept such as closures and higher-order function.

There are some other syntax that I believe can also be solved with higher-order function and closures. First thing comes to my mind is the inheritance. But that would be story for other day.

I wrote this article because I believe these syntaxes are introduced into TypeScript because a lot of developers familiar with traditional object-oriented programming (I was once) would like to have something they familiar with.

And that is okay, you should have language with all syntax that make you feel comfortable working with. Our purpose writing code is not to write the “most beautiful code”, but to solve business problem through writing code.

IMO, You should go for whatever syntaxes make you and your team be most productive. I don’t think there are any point using elegant syntax or elegant language for the sake of the elegance alone.

Still, I believe some developers, coming from traditional object-oriented background, may not yet realized power of closures and higher-order function yet, and may not yet see how this tool can solved a lot of traditional object-oriented problems and syntaxes.

That is why I wrote this article. I want to demonstrate power of functional-programming paradigm such as closures and higher-order function as a choice. Wether you use it in your team? It will be up to readers to decide.

In my opinion, if I build a completely new team, I would like them to learn closures and higher-order function rather than multiple concepts such as decorators, inheritances, etc. I will use only that in codebase. I believe it is more productive for developers to remember just only one or two concept and use it to do many things in codebase.

But if condition changes, if I build a team with a lot of programmer with Java or C# background, I may use the decorator syntax, since they are already familiar with the concept.

Just my thought that I want to share.

--

--

Chris
Chris’ Dialogue

I am a product builder who specializes in programming. Strongly believe in humanist.