I have a case where I want a callable object, or at-least the feeling of:
{}()
{}.prop
I am not the biggest fan of classes in the world but I have to admit it they have been getting some special treatment of late so in my case its unavoidable. private fields, class field and more. Anyway to achieve the following in a non hacky simple kind of way we need to do this:
Worth a note that this is typescript but should work in JavaScript too.
class Dog {
static legs = 5;
constructor() {
console.log('woof');
}
}
// progmatic use of `new` via .construct
// preload the first argument with the class we want to call;
// proxy the actual Reflect.construct method but point all gets and sets to the static Class constructor, in english: makes static available NOTE this does not mess with Reflect.construct
const callableObject = new Proxy(
Reflect.construct.bind(null, Dog),
{
get(tar, prop, val) {
// access static
return Reflect.get(Dog, prop, val);
},
set(tar, prop, val) {
// access static
return Reflect.set(Dog, prop, val);
},
apply(target, thisArg, argumentsList) {
// make the constructor work
return target({...argumentsList, length: argumentsList.length});
}
}
);
callableObject(); // calls constructor
callableObject.legs; // 5
magic :)
Top comments (5)
Reflection is always so magic! I've used them in a couple of situations in my code, and when I come back to them, I have trouble to understand what's happening because it's too magical to remember Β―_(γ)_/Β―
I know thats the problem, they are not idiomatic. I tend to write libraries, lots of libraries and I always want to give the best experience for developers, usually thats why my libraries never get finished. So I do usually avoid magic, the thing is I am doing code generation via typescript and reflection and so I needed to do this stuff.
The above code is a snippet from my abstraction over Regl, I am attempting to create a reactive webgl framework in the style of Vue.js.
Reactive webgl, that sounds like a great idea! I hope you share it!
I completely see the point of reflection within libraries, abstracting their "magic" from the developers that use them and offering features that weren't possible before.
I struggled when I use reflection for the business logic... I just won't do it anymore :D
I highly recommend writing a helper function which returns an instance of the class. This lets you exactly control the return type. For example, that's how I prefer to do private fields/methods/etc.:
To keep typings do this (@ts-ingore is required but everything still works):
My English skills might not be perfect, so I apologise if my ideas overlap with earlier contributions. Nevertheless, Iβd like to share my approaches to solving the problem of calling a constructor in TypeScript without using the
new
keyword.Nevertheless, as in the topic 'Simple trick to instance a class without
new
.' , Here are my solutions to the problem, each addressing different scenarios and requirements.:π¨1οΈβ£π °οΈ
The utilisation of this particular pattern serves to guarantee that instances of a given class are created exclusively through the designated factories or static methods. This functionality is particularly advantageous in scenarios where stringent control over the initialisation of objects is required.
π©1οΈβ£π ±οΈ
πͺ2οΈβ£π °οΈ
private constructor
refers to a constructor that is not publicly accessible. The constructor is private, preventing the creation of class objects using thenew
keyword outside the class.getInstance
method: This method is employed to create or return an existing instance in a controlled manner.instance
property, it is ensured that only one instance of this class is ever created.π₯2οΈβ£π ±οΈ
π§3οΈβ£π °οΈ
π«3οΈβ£π ±οΈ
set/get
)async/await
handling.set
andget
.async/await
handling.async
with Singleton logic.async
.