r/node • u/EveYogaTech • 9h ago
Experimental Superset of Node to support JavaScript Types in functions.
https://github.com/flowagi-eu/jstf6
u/alex-weej 9h ago
2
u/EveYogaTech 9h ago
Nice collection, however it assumes that we cannot find a way to support types natively and faster in the future of Node/similar JS runtime.
Bun for example, also just transpiles TypeScript.
3
u/fucking_passwords 8h ago
I feel like this would be better as a decorator / annotation for TS that builds in the runtime checks.. something like:
@RuntimeTypeChecks
function foo(bar: number, baz: string) {}
That way you could avoid runtime type checks for every single function and just focus on the ones that process unknown input. I get that you are positing that TS is too verbose/complex but we will have to agree to disagree on that one
0
u/EveYogaTech 8h ago
This could work if your goal is to extend TypeScript.
The goal of this project is to extend JavaScript.
0
u/EveYogaTech 8h ago
I'd also add that decorators might be tricky, because you (or a junior engineer) might forget the decorator and on a quick look it looks like types are defined while in reality they are only transpiled.
5
u/its_jsec 8h ago
https://github.com/flowagi-eu/jstf/blob/main/bin/jstf.js
What in the world did I just read.
1
u/gdmr458 6h ago
holy shit, i was too optimist, before clicking the link op posted i thought they cloned https://github.com/nodejs/node and wrote a lot of C++ code to make this work
0
0
u/EveYogaTech 8h ago
It works though.
4
u/its_jsec 7h ago
Does it?
Your findFunctions regex only checks for `function {more matching}`. How does it handle functions as const expressions?
The node_modules check uses “/node_modules/“, which won’t match on Windows.
And this isn’t a superset of Node (how one would superset a runtime is beyond me).
This looks like you’re running a .js file through esbuild’s TypeScript loader, then splicing checks into the emitted output based on a captured function name (with the name map being a flat map, so a function that has the same name as a closure-scoped function will yield interesting results). Why not use an AST tree?
3
u/boneskull 7h ago
parsing the AST would be even slower!
1
2
6
u/boneskull 7h ago
Apologies OP, but this is truly cursed. I think you will find it is better in the long run to actually write these type guards. You don’t need to use Zod or whatever, but the current implementation is not at all robust and has quite a few problems beyond simply performance.
You mention this is for an open-source project; if you have hope of gaining contributors you may want to steer away from something like this.
1
u/EveYogaTech 7h ago edited 6h ago
I agree the current implementation is not yet super robust and experimental.
However I'd say it depends on what's possible and feasible in the long-term.
We could even add meta data about types to functions (e.g. directly in v8/webkit) and in essence "compile JavaScript".
2
u/Beginning-Seat5221 5h ago edited 5h ago
All I'm going to say is that Node.js isn't a language, it's a runtime. I'm not sure if you can have a superset of Node.js.
I think "superset of JavaScript" is probably what you're aiming at here?
You'd also probably be better off making a TypeScript pre-compiler or post-compiler - keep the surface language TS for TS tooling/ecosystem and just use comments to opt functions in for a pre-compile or post-compile that keeps each stage valid TS or JS compatible with everything in the ecosystem (although people have been doing this with babel for years already).
1
u/DLabz 6h ago
Javascript + JSDOC + //@ts-check is what works for me.
You can go wild with defining parameters and IDE will do type check your code, show hints and snippets when you hover a function, show documentatation, generate AST graphs, link debugger breakpoints back and what not, all without ever needing a compilation step to run or enforcing types at runtime, which saves you from needing to explicitly dode every and any special/edge/cornet case for your code to run, while allowing you to transpile it to TypeScript using tsc.
At the end of the day, loosely typed is a feature, not a deficit.
1
u/EveYogaTech 6h ago
That can appear to work, but it still doesn't check types at runtime (e.g. when you are working with dynamic incoming user/API data).
1
u/DLabz 6h ago
That’s a good thing, because I can pass just about anything to a `(o)=>o.k + o.v;` function and it will not break.
When I want a tighter check I’d use decomposition `({k,v})=>k+v` set defaults, or check specifically ([m=2,n=3,…r]) => [m, n, … r.filter((n)=>! isNan(n)]
I don’t need to write a separate dotVector for 2D, 3D or nD
1
2
u/EveYogaTech 9h ago edited 9h ago
A bit of background:
I tried both JavaScript (Node) and TypeScript for our open-source solution, but kept running into the problem of actually needing to validate types at many places, primarily in functions.
Initially TypeScript seems to be the solution, but if you look at the compiled source code you will see that there is actually no type checking at all, after you compiled your TypeScript to JavaScript, which at runtime can cause problems.
The common solution for this is to then use runtime libraries like Zod, practically often only at the HTTP layer.
JSTF takes a different approach where you can (optionally) define types in all your functions similar to TypeScript that are checked at runtime.
0
u/CreamyJala 8h ago
> You look at the compiled source code you will see that there is no type checking at all
That’s kind of the point of Typescript, though. You’re able to catch the obvious problems ahead of time, get out nearly identical JavaScript code from the compiler, and still be able to debug with ease.
If your goal is safety and avoiding problems, then you would’ve considered the implications of what could (and will) go wrong when injecting “invisible” code like this, especially with projects that have multiple collaborators.
If your goal was to have fun and not use this seriously, then go for it - have fun with it! If you’re convinced that this is the proper approach and are going to use it on anything important, just be aware of the risks and footguns, and maybe chill on your tokens for a bit
2
u/EveYogaTech 8h ago
> considered the implications of what could (and will) go wrong when injecting “invisible” code
This is broadly true for every compiler ever made. In practice, I don't think many people besides reverse engineers are debugging machine code.
1
u/boneskull 7h ago
that’s not what the commenter meant. you need source maps or debugging will be excruciating
1
14
u/frogic 9h ago
Uh. I think you might have accidentally created the most performance nightmare thing I've ever seen.