# Node-RED: Creating a custom node using TypeScript

Welcome! In this brief article, I will outline how to create a custom Node-RED node using TypeScript.

I have published a small library that allows TypeScript to be used in Node-RED. If you just want to use it, you can find it [here](https://www.npmjs.com/package/node-red-contrib-typescript-node). If you are interested in how it works, I invite you to keep reading!

![Photo by [John Barkiple](https://unsplash.com/@barkiple?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)](https://miro.medium.com/max/1400/0*dPY2wdYthEF2ddU6?q=20)

> [Node-RED](https://nodered.org/) is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways.

## Motivation

Work on my Master’s thesis gravitated towards creating some Node-RED nodes. Being an avid fan of TypeScript and its benefits, I decided to research the topic of developing nodes using the language, instead of the [recommended ES5 “classes”](https://nodered.org/docs/creating-nodes/first-node#lower-casejs). This article outlines how I achieved a solution.

# Introduction

A custom Node-RED node is mainly comprised of a `.js` and a `.html` file. The goal of this post is to show how to replace the `js` file with a `ts` file by leveraging the knowledge of how JavaScript works and making use of the TypeScript compiler.

_Note: As of the writing of this article, I haven’t found a way to replace the JavaScript in the HTML file with TypeScript. Anyhow, the amount of JavaScript in this file is generally so reduced that the benefit earned by using TypeScript in this context would be small._

# Understanding the Vanilla Way

Reusing the [example](https://nodered.org/docs/creating-nodes/first-node#creating-a-simple-node) present in the official documentation, we will be building a node that transforms the messages it receives into all lower case letters.

For this, two files are necessary, namely `lower-case.html` and `lower-case.js`. Their function is outlined very well in the documentation:

> [Nodes] typically consist of a pair of files; a JavaScript file that defines what the node does, and an HTML file that defines the node’s properties, edit dialog and help text.

The HTML file configures the settings and the interface displayed in the Node-RED’s web UI and, as such, is not very interesting for the purpose of this article.

The JavaScript file is the one that effectively implements the logic of the node and so this is the one we’ll be looking into more closely.

-----

This is how the [official documentation](https://nodered.org/docs/creating-nodes/first-node#lower-casejs) requires a node to be structured:

```js
module.exports = function(RED) {
  function LowerCaseNode(config) {
    RED.nodes.createNode(this,config);
    var node = this;
    node.on('input', function(msg) {
      msg.payload = msg.payload.toLowerCase();
      node.send(msg);
    });
  }
  RED.nodes.registerType("lower-case", LowerCaseNode)
}
```

For new users of JavaScript, this syntax may seem weird. In fact, it was how classes were written before ECMAScript 6 came along. You can read more about pre-ES6 classes and prototypes [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype).

Long story short, the `LowerCaseNode` function is acting as a constructor of the `LowerCaseNode` class. Inside the function, `this` refers to the object being constructed.

Node-RED will then add some properties to the prototype of `LowerCaseNode`, such as the `on()` function we see on line 5\. We will be leveraging this knowledge in order to use classes in TypeScript.

It should also be noted that we are passing the constructor of the class as the second argument of the `registerType` function, on line 10.

Given these two pieces of knowledge, we can force the TypeScript compiler into generating the code we want.

* * *

# Onto TypeScript

The TypeScript compiler not only transforms TypeScript code into JavaScript, but is also capable of selecting the version of ECMAScript to compile to, by utilizing the `target` option present in [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/compiler-options.html).

By setting the `target` option to `"es5"`, we can obtain the ES5 code Node-RED expects.

* * *

Having updated `tsconfig.json`, we can finally dive into the actual code.

As said before, we’ll be using a class to write the `LowerCaseNode`. This requires the constructor to have the same signature (line 3). Also, inside the constructor, we can now use `this`, instead of the previous `var node = this;` workaround.

Finally, we have to call `registerType` passing the class itself as the second argument.

```ts
module.exports = function (RED: Red) {
    class LowerCaseNode {
        constructor(config: NodeProperties) {
            RED.nodes.createNode(this, config);
            
            this.on('input', function(msg: any) {
                msg.payload = msg.payload.toLowerCase();
                this.send(msg);
            });
        }
    }

    RED.nodes.registerType("lower-case", LowerCaseNode)
}
```

If we compile the above example, we’ll get the following compiled JavaScript code:

```js
module.exports = function (RED) {
    var LowerCaseNode = /** @class */ (function () {
        function LowerCaseNode(config) {
            RED.nodes.createNode(this, config);
            this.on('input', function (msg) {
                msg.payload = msg.payload.toLowerCase();
                this.send(msg);
            });
        }
        return LowerCaseNode;
    }());
    RED.nodes.registerType("lower-case", LowerCaseNode);
};
```

_Note: You can play with the_ [_code_](https://www.typescriptlang.org/play?#code/LYewJgrgNgpgdDAHgBxAJwC4GcAEBeHAMwgDsBjDASxBJwAoAlAUQBEBKHAbwFgAoHATjJQAhllwAZEAHcYaAMJiYAOXAwufQVqE0sGNBAro6ZGoUoBzAFw4RJAJ4ce-ba+Ys4JNVjhk0MEQwVNToMAAtKLAAaUxJzCzYAbk1XbQA3ETQcLzB1AnDI5JdUwRz4GjoAckoSZAgMSqiiUgpqEjpgLASNYpLtTos4ZBF7KBARMHwcAaGRsYm4DBApWQUlOiSUvu0yuCwYEjAOrs3ekoBfU4utnHOb909vOH8LSKC0ABV7ZBg6ACIxqsALRkJR-JorOSKfaqXJsPjnIA) _on the TypeScript Playground to see how changes affect the output._

We can observe that the output is almost identical to the official Node-RED example. There is, however, a small change. The variable `LowerCaseNode` (line 2) now refers to an _Immediately Invoked Function Expression_ ([read more](https://developer.mozilla.org/en-US/docs/Glossary/IIFE)) that returns the constructor of the `LowerCaseNode`.

In the end, the difference is not problematic and the node will work as expected.

This concludes the small proof of concept that illustrates how to use Node-RED with TypeScript.

* * *

# Conclusion

Hopefully, not only did you understand how to write a Node-RED node in TypeScript, but also why and how it works.

You can now [test your own components](https://nodered.org/docs/creating-nodes/first-node#testing-your-node-in-node-red) in Node-RED using the constructs mentioned in this article.

**Thank you for reading 👏**

_If you are interested in using a more higher-level (although still very basic) library, you can_ [_check_](https://www.npmjs.com/package/node-red-contrib-typescript-node) _the one I published._

_Make sure to leave feedback, suggestions and/or corrections._
