Interfaces in JavaScript with ES6 Symbol. Naive implementation
As we know, javascript has own approach to implement OOP, this is different from approaches in C# and Java, and in earliest days before ES6 javascript does not support class
, and inheritance was implemented by prototypes
or some custom implementation. After class
became a part of the javascript and started widely used there, many people start require make one more step, and make interface
as the part of the javascript. To respond this people was proposed first class protocols, this spec on Stage 1. So it will not be so soon till it will be part of the language. How we can implement this in current state of the javascript:
- Do not implement and just use Duck Typing. Sometimes, this approach is good enough, but there are a lot of cases where this approach can lead to some unexpected behavior of the application.
- Use library or transpiler for interface. There are bunch of the different libs that allow to implement interface within javascript code. I’ll not stop on this approach, because in our project we decided do not rely on any external lib.
- Use TypeScript. TypeScript as superset of javascript support of the interface, but switching the our project to TypeScript was a big change for us.
- Use
Proxy
. Unfortunately it is not supported by Babel:Due to the limitations of ES5, Proxies cannot be transpiled or polyfilled. See support in various JavaScript engines
- Use data type Symbol. In ES6 spec was added new data type
Symbol
. It has very important characteristic:
Every symbol value returned from Symbol() is unique
So based on this characteristic we built our approach to support interface in project.
We create property in class with Symbol
name that return object with the implementation of the interface. Using of the Symbol
prevent from existing in object some property that named in the same way as interface.
Yeah, it is quite naive approach, but allows to answer question if object implement interface. We can go father and use Symbol
as name of each function in interface, but in our project we decided that it is enough to use Symbol
only for name of the interface.
Actually ES6 generator also use this approach to implement iterator/generator in any object: