I am exporting the following ES6 class from one module:
export class Thingy {
hello() {
console.log("A");
}
world() {
console.log("B");
}
}
And importing it from another module:
import {Thingy} from "thingy";
if (isClass(Thingy)) {
// Do something...
}
How can I check whether a variable is a class? Not a class instance, but a class declaration?
In other words, how would I implement the isClass
function in the example above?
If you want to ensure that the value is not only a function, but really a constructor function for a class, you can convert the function to a string and inspect its representation. The spec dictates the string representation of a class constructor.
Another solution would be to try to call the value as a normal function. Class constructors are not callable as normal functions, but error messages probably vary between browsers:
The disadvantage is that invoking the function can have all kinds of unknown side effects...
What about:
I'll make it clear up front here, any arbitrary function can be a constructor. If you are distinguishing between "class" and "function", you are making poor API design choices. If you assume something must be a
class
for instance, no-one using Babel or Typescript will be be detected as aclass
because their code will have been converted to a function instead. It means you are mandating that anyone using your codebase must be running in an ES6 environment in general, so your code will be unusable on older environments.Your options here are limited to implementation-defined behavior. In ES6, once code is parsed and the syntax is processed, there isn't much class-specific behavior left. All you have is a constructor function. Your best choice is to do
and if someone needs to do a non-constructor function, expose a separate API for that.
Obviously that is not the answer you are looking for, but it's important to make that clear.
As the other answer here mentions, you do have an option because
.toString()
on functions is required to return a class declaration, e.g.The key thing, however, is that that only applies if it can. It is 100% spec compliant for an implementation to have
No browsers currently do that, but there are several embedded systems that focus on JS programming for instance, and to preserve memory for your program itself, they discard the source code once it has been parsed, meaning they will have no source code to return from
.toString()
and that is allowed.Similarly, by using
.toString()
you are making assumptions about both future-proofing, and general API design. Say you dobecause this relies on string representations, it could easily break.
Take decorators for example:
Does the
.toString()
of this include the decorator? What if the decorator itself returns afunction
instead of a class?Maybe this can help