Dreaming of typescript

Imagine for a second the possibility of typescript support in addition or instead of javascript. What would that look like? You could declare the type of each output connection, and by that get notification whenever you wire up nodes that are incompatible! You would be notified when access a property in msg that doesn't exist (instead of finding out eventually...). The feedback loop is instant! It would probably be enough to declare the output type, and the rest would solve itself. I am currently managing several NR instances for monitoring and controlling building energy, and more often than I'd like, there are some part in need of updates. But when copying code and apply to all instances, well they're not all identical. Sometimes it will be logged, other times it will not. I don't test everything every time. Regression bugs do happen from time to time. Ts would eliminate most if not all of them instantly. I know that an alternative ts function node exists, but last time I checked it doesn't support NR lint, not willing to make that choice. As much as I enjoy js, I started a ts project recently and realized how much I missed it. My dream of first-class support in NR continues.

NO!!!!

This would kill Node-RED for me. Even the use of Typescript in some areas of Node-RED code would likely end any attempt by me to offer support or extension.

Also, have you used VSCode's typescript support in writing JavaScript for the DOM? It STINKS! I generally have to turn it off as it gets so many things wrong ("property X does not exist on HTMLElement"! Cr&p.)

Typescript is useful for large development teams. It is just another non-native language getting in the way for us hobbyists.

2 Likes

Julian likes typescript - can you tell? :smiley:

Getting very close to releasing v11 of my Node, it did start as a typescript project.

it become to involved, and..... unnecessary?

I don't mind typescript - but I would have to agree with Julian, better left for extremely large projects, where MANY developers are involved, that might not know the types involved in said project

2 Likes

Check out my uibuilder nodes. They are chock full of JSDoc based type direction. I even now produce a typedefs file for the client library (but only because Claude can do it for me, if I didn't have that, I couldn't/wouldn't do it). As I say, I often have to turn off the typescript linting due to the poor support for certain types of object (notably the DOM and Node-RED!).

The JSDoc typings are mostly in collapsible comments so they don't get in the way of programming but VScode still gives me hints and whinges at me if I've gone too far off the rails.

1 Like

It is enough to write a prop slightly different in one instance to make all sorts of problems that turned out to be invisible except for some missing output (among a lot of output). Could be you or another team member forgot precisely how to name that prop. And for how long do you remember the exact names of props anyway? Months? weeks? days? 1-2 people is hardly a big team!

Currently working on a react project and seems smooth so far in vscode. I will be adjusting configs and settings ruthlessly to get the correct feedback. But for this topic, can set strict mode default off as compromise haha.

You have a TEAM for writing nodes? I think most of us are single devs. :smiley: By all means use TS to create you nodes, this is entirely up to you. Just don't, please, force it on those of us for whom it is an unnecessary overhead with no benefit.

We have a team working professionally using NR yes. Life is great!

1 Like

@ThingsTinkerer nodes written with the NRG (acronym to node-red generator) framework are going to fix that

I'm very close to releasing it. Input/Outputs/Configs/Credentials/Settings are all typechecked at runtime and build time. Nodes are properly encapsulated using classes and are typed during development. For example, inside a node you can now get runtime typed config nodes

// NOTE: remoteServer is a config node
const server = this.config.remoteServer;
if (server instanceof RemoteServerConfigNode) {
   // NOTE: this message will be logged :D
   this.log("server is an instance of RemoteServerConfigNode");
}

Disregard the README docs, because lot of things have changed and read the code in ./server and ./client folders to understand how to create nodes.

I recommend not writting nodes with it yet because I'm still working on the API design and dev tooling. Things might change. Just use it to learn and give me feedback if possible.

Besides improving the overall design of nodes, I also developed vite plugin to ease development, and standardize the distribution of packages.

pnpm dev   => start dev server
pnpm build => create distro at ./dist

This template will be part of the NRG CLI v3.

1 Like

Of course, there is only 1 minor issue when writing nodes in TypeScript even now. That is that the compiled output likely won't have the same source lines as the source code so debugging errors can be somewhat tricky. I discovered that myself when I played with a build step using ESBUILD for my nodes (one of my experiments when looking to be able to use ESM's for nodes prior to node.js catching up with allowing ESM's in CommonJS modules). There is a work-around but it requires running Node-RED with a node.js flag to allow the use of map files.

Perhaps I should clarify, I don't write nodes as in design nodes as packages/palette. I write function nodes and make subflows in NR. It covers 90% of what I need and the rest seems like a big jump. But having automated instant feedback on all props in all these function nodes and subflows would be great. Perhaps ts could even "see" how a msg builds up and make type dynamically from it instead of predeclaring all types.

OK, I get it. :smiley:

For sure. But one opposing thought if I may. One of the strengths (IMHO) of Node-RED is that you DON'T have to concern yourself with enforced schema's. This is what makes NR such a great prototyping tool. And it lends itself to things like home automation.

So while I certainly see the benefits of having such things available, in my view, they should never be mandated. Such as might be implied from your first post and why I responded so vehemently.

Indeed, such a change would destroy the flows of, I would guess, by far the majority of people. And would add significant complexity to many flows since you would now need to provide handling for edge cases and complex data inputs that previously you might have been able to ignore.

I'll go as far as grant you strict mode off haha :grinning_face_with_smiling_eyes:

FYI: There is already an ongoing discussion about node type definitions on Github :wink:

1 Like

A sensible approach. Nice to see a basic start targeted for v5.

Note also that a more realistic approach is to use TS types in combination with JSDoc comments. This benefits both the core and third-party developers.

1 Like

@AllanOricil I saw your comment on the issue, I was in the middle of replying but the comment has since been deleted, so I'll reply here.

The issue is the start of the discussion. You have implemented an entire framework with NRG without any discussion or consultation. You have declared you have the best solution. That may be the case, but we need to evaluate what is right for the core Node-RED experience.

The question over whether TypeScript typings or JSON Schema based solutions (or Zod, or something else) is an active one. There are trade-offs across the board on it and lots of different use cases to consider.

I'm not personally a fan of TypeScript definitions for nodes as we need a mechanism that can apply to not only node properties, but also the messages they send and receive.

We need a mechanism that can statically validate a flow json - without having to run nodes to access their schemas.

My current thinking is that JSON Schema works at the base layer - but doesn't preclude building a tool chain on top that generates the schema from TypeScript/Zod or whatever the node author wants to do.

3 Likes

This has already been sorted too. Configs, Credentias, Settings, Input and Outputs messages. All dynamically typed with the source of truth being a Typed Json Schema, made with Typebox. I didnt use zod because it is slow and it is not compatible with json schemas. Typebox let us generate and export types and json schemas. It also let us use plain json schemas if people dont like using typescript to declare them. Just look at my work.

1 Like

Where should we be looking? I know you've shared links previously in other threads, but it would be helpful to have a link rather than have to go digging for it.

As I said, my current thinking is the base layer should be JSON Schema. If a node author choses to use a toolchain/framework to generate that schema, then that's great - and there's plenty of space for that to happen. But they key, at this stage, is to get the base layer defined.

Another key point is we need a mechanism for existing nodes to declare typings without forcing them to complete rewrite themselves in a particular framework. That means keeping it as light-weight as possible for an existing module to adopt.