Various attempts to create TypeScript constructors
that can be invoked with and without the new
keyword
like several built-ins including Array
et al.
I am not 100% happy with any of those solutions. Any feedback with better ideas is more than welcome.
I would especially like to:
- eliminate all
any
types (without making the proxy wrapper specific to one particular type - which is tricky, if possible at all) - eliminate proxies (currently I don't think it's possible but hopefully I'm wrong)
I will appreciate any help with that.
This is my old code that I was playing some time ago in 2018. I'm putting it online in case it is useful to someone.
All examples is in a separate directory with its own tsconfig.json
file
to avoid errors of the same symbols defined in multiple files.
The tsconfig.json
is as strict as possible, with all options turned on that I usually recommended. It made it harder to write the code but it is at the same time more useful in different compiler configurations.
The idea is to match the built-in costructors like Array
as closely as possible. There are several important things to keep in mind:
- It should be all correct TypeScript with strict type checking
- It should use
class
keyword instead of defining the constructors as old style functions - The compiler should understand the types and the VSCode editor should correctly detect errors like a typo in a method name exactly the same as normal constructors with
new
keyword in TypeScript - no type safety compromises - Both
a = new A()
anda = A()
should work the same - In both cases
a instanceof A
should betrue
- In both cases
a.constructor.name
should be'A'
- In both cases
console.log(a)
should printA {...}
- Another constructor
B
should be able to extend (inherit from)A
usingclass B extends A { ... }
syntax - Both
b = new B()
andb = B()
should both work - In both cases
b instanceof B
andb instanceof A
and should betrue
- In both cases
a.constructor.name
ahould be'B'
- In both cases
console.log(a)
should printB {...}
Optional requirement (is it important? or can it be harmful?):
- In both cases for the base class (
a = new A()
anda = A()
)a.constructor == A
should betrue
- In both cases for the child class (
b = new B()
andb = B()
)b.constructor == B
should betrue
Can it even be done without proxying the instances or changing the costructor to redefine the constructor
property of the object? (which can be made non enumerable but would still return true
for hasOwnProperty
) It may not be worth the hassle but I may be wrong here.
If you have some other important feature that is not listed here, please post an issue.
The exampels are in separate directories.
The rsp-2-*
ones are most useful. All of the rsp-0-*
and rsp-1-*
as well as the bak*
directories are mostly for backup archives
but feel free to explore my early attempts (but not everything can work).
The only dependency is the TypeScript compiler.
If you don't have the TypeScript compiler installed globally then install it locally with:
npm i
and use it as npx tsc
as shown below.
If you have the TypeScript compiler installed globally then
you can use tsc
instead of npx tsc
in the examples below.
To run the rsp-2-4
example:
cd rsp-2-4
npx tsc
node build/*.js
or:
./run rsp-2-4
It will print some output that is relevant to the required features of the given solution. If you need more info just add it to the source code.
For any bug reports or feature requests please post an issue on GitHub.
MIT License (Expat). See LICENSE.md for details.