Object interfaces allow you to create code that specifies which methods a class must implement, without having to define how these methods are implemented. Interfaces share a namespace with classes and traits, so they may not use the same name.
In practice, interfaces serve two complementary purposes:
Iterable
, Cacheable
, Renderable
, or so on to describe the significance of the behavior.https://www.php.net/manual/en/language.oop5.interfaces.php
There’s no notion of “this class must have these functions” (that is, no interfaces per se), because:
Instead, JavaScript uses what’s called duck typing. (If it walks like a duck, and quacks like a duck, as far as JS cares, it’s a duck.) If your object has quack()
, walk()
, and fly()
methods, code can use it wherever it expects an object that can walk()
, quack()
, and fly()
, without requiring the implementation of some “Duckable” interface. The interface is exactly the set of functions that the code uses (and the return values from those functions), and with duck typing, you get that for free.
https://stackoverflow.com/a/3710367
Note: JavaScript has the reserved word interface
in case they ever would like to implement interfaces
In my personal opinion, no.
Recently, in order to increase my practical JavaScript knowledge, I have been working on both JavaScript and TypeScript projects. The lack of interfaces made it difficult to implement things in JavaScript that I had architected with PHP in mind. I also began, as a practice project, to try to clone certain small PHP packages in JavaScript but regularly ran into the issue that JavaScript lacks interfaces where PHP does not.
This is when I came up with an idea to create my own “interface” in JavaScript.
The first thing I did was to create a new class with Interface as the suffix in the class name. This will help you differentiate what is an implementation and what is an interface when looking through files. In this case, let’s call our class MyInterface
module.exports = class MyInterface {
}
I then created all the methods that I wished the implementers to implement but created them as empty methods.
module.exports = class MyInterface {
/**
* @param {string} var1
* @param {string} var2
*
* @return {string}
*/
firstMethod (var1, var2) {}
/**
* @return {string}
*/
secondMethod () {}
/**
* @param {string} var1
*/
thirdMethod (var1) {}
}
The next step is to “implement” the interface. What we are really doing is extending the MyInterface
class, but if we try to use the methods of the implementation class and we do not implement them, it will cause issues because there will be no actions occurring on the method calls.
const MyInterface = require('./MyInterface')
module.exports = class MyImplementation extends MyInterface {
myVar
constructor (theVar)
{
this.myVar = theVar
}
/**
* @inheritDoc
*/
firstMethod (var1, var2)
{
return var1 + var2
}
/**
* @inheritDoc
*/
secondMethod ()
{
return 'secondMethod'
}
/**
* @inheritDoc
*/
thirdMethod (var1)
{
this.myVar = var1
}
}
I know this isn’t a perfect solution, but I see it as good enough for solving the design implementation problems. This will allow you to also set the return type to the interface even when you are implementing. It will also not let you try to instantiate the interface class as there is no constructor defined.
/**
* {MyInterface} myObject
*/
const myFunction = () => {
return new MyImplementation()
}
I am perfectly aware that there are many ways to work around this and subvert the type system. I only wrote this post so that anyone who wanted to try to introduce interfaces into their JavaScript designs could have a way to do so.