JonScript: a better JavaScript

I created my own alternative language to JavaScript.

Jan Jindráček
JavaScript in Plain English

--

Introduction

Hello! Do you like JavaScript? If not, please, don’t click away yet. As a JS developer, I understand your pain when you have to use it, and I think I may have a solution: a new language that compiles into JavaScript! I know that such statements have become a meme by themselves and are frequently parodied by developers. But, hear me out: this time, it may be different.

I think you might have heard of the horror stories of JS development going wrong. These horror stories have proliferated throughout the world of programming and spawned many a meme at which us JS developers laugh, so we don’t cry:

Source: https://dev.to/damxipo/javascript-versus-memes-explaining-various-funny-memes-2o8c

On the other hand, JavaScript is the most popular (or “popular”) language in the world and has been for a while. It is the backbone of web development, has many amazing features, and a wide range of frameworks and extensions. The most significant reason for this prevalence are JS’s close ties with the web browser. In the age of ubiquitous web applications the language that runs in the web browser cannot help but be popular. And, of course, another big part of the reason for JS’s sustained prevalence is its already existing user base: people use JS because it’s popular.

And some of the popularity is even earned! For instance, JS is a great prototyping language. If you want to sit down and write a quick app to test an idea, JS will work for you. It also proliferates many of the neat functional programming features that make many common types of boilerplate patterns melt away. There’s also a whole ecosystem of useful packages and frameworks that make web development easier.

So there are reasons not to hate it.

But there are many reasons to hate it though. Let’s go through the big ones, one by one.

One. There are too many ways of doing the same thing. I can name two or three ways of creating an object, 3 ways of defining a variable, and three or four ways of defining a function. The sheer variety can be overwhelming, but an experienced dev might say: “But these are just details! We should focus on what the code does, not the syntax”. However, things are not that simple.

There are not just syntactic differences, but actual, subtle and dangerous differences during runtime. For me they are basically a mechanism to introduce subtle but significant bugs. But don’t take my word for it, the Internet is full of posts attempting to help people navigate these variations.¹ ¹⁰

Two. The standard library is inconsistent. There are many examples out there, but consider how you would represent 1st of April 2021 using JavaScript’s Date class. It would be something like this, right:

new Date(2021, 4, 1)

No, of course not. That is very clearly 1st of May, because months (and only months) are zero-indexed. Even the people who wrote it wash their hands of it¹¹. “Well, actually” I already hear you saying, “there is a reason for it. It’s a long standing tradition for programmers to represent months like this. After all, the month is not actually a number, it’s just a numeric representation of an enumerative type. Here, look at POSIX localtime.”¹² Perhaps it is one of those harmful traditions that we should let go of.

Three. Not a Number is a number. When you execute invalid operations related to numbers, the result can be NaN. If you try to do a type check on such a value, it acts as if it was a regular number.

typeof NaN === “number” // is true

It adds like a number, it divides as a number, and, crucially, it prints and concatenates as a number (sometimes). But you don’t want “NaN%” on your website.

Source: https://www.pse.cz/en/detail/CZ0009004792, the Prague stock exchange site

JS developers would be better off without it.

Four. There are lots and lots of weird semantics. For instance, in contravention to all laws of mathematics a JS object is both unequal to an otherwise identical object while being simultaneously greater equal and less equal to it.¹³ “But!” you might say “Mathematics is one thing, but these symbols don’t mean the same operation in JavaScript as they do in Mathematics. If you had but read the description of these operations in the standard it would have been clear.“ But there are a lot of these traps out there¹⁴ and we can’t expect everyone to always instantly recognize them, especially not someone new to JavaScript.

Five. Classes aren’t what they seem. ES6 adds several keywords to the language. One of them is class. This is because the language needed to be more welcoming to new developers.

But this is a double-edged sword¹⁷. When a developer sees the word class, they make several implicit assumptions. The most important of these are: methods can’t be redefined, objects can’t change classes at runtime, classes don’t have dynamically generated properties. That’s how classes work in Java, C++, Python, and other languages they might be familiar with.

But in JS these assumptions are incorrect. JavaScript doesn’t have a class based inheritance system. JavaScript uses its own version of prototypal inheritance,¹⁸ which allows much more flexibility, but it’s easy to misunderstand.

class Bitcoin {
constructor(value) {
this.value = value;
}
valueOf = () => this.value;
}
// Define another public function
Bitcoin.prototype.next = function() { return this.value * 2; }

This looks like a class definition with one public function, right?

Given that this is a class, you’d expect this definition to be immutable, right?

These assumptions may end up breaking a new JS devs app — therefore causing many headaches.

Me vs other people

Ok, but maybe it’s just me. Maybe what it means to be a JavaScript expert is to effortlessly navigate these treacherous shoals and all the really advanced JavaScript developers find my objections quaint. Luckily for me, I happen to work with some professional JavaScript developers with long and impressive CVs, so I asked them.

I made a test with 12 questions checking the understanding of semantics, each of which a cunning trap set for the developer. It’s a multiple choice test with three possible answers for each question, one of them correct. The questions present code examples and ask the victim participant to interpret the semantics of JavaScript and its standard library. The participants had unlimited time to answer each question. Here’s an example question:

If `window` has 222 properties, what is the value of variable `c` after executing:

console.log(t); const c = Object.keys(window).length; var t = 1;
  1. undefined
  2. 222
  3. 223

You can see all the questions here — https://ivlv.me/kNgHW and the reasoning behind them. You can try your luck at answering them too. (But no cheating!) It’s not the most scientific of studies, sure, but I think the results are illustrative.

The highest score was 7 out of 12, others were below 4. The results from my small focus group show that even experienced JavaScript developers have trouble differentiating between language primitives, their class counterparts, execution context-dependent functions and the behavior of Date and Object classes, typeof¹⁵ and instanceof¹⁶ operators and more.

So even experienced JavaScript monkeys get this stuff wrong all the time. Does that matter? Perhaps these weird situations don’t come up all that often and this is all just trivia, but it seems like these subtleties would cause real world bugs (I could point to the Prague stock exchange again).

Links: http://www.ece.ubc.ca/~frolino/docs/js_bugs_study_paper.pdf

What do we make of this?

OK, so the language is bad. But more importantly a question puts itself forward from endlessly enumerating my grievances. Why is JavaScript like this? It’s not like it isn’t under the care of some very competent people. And given the state of the internet, it’s not like they don’t know that these problems exist.¹¹

JavaScript is a common language without a lot of control over its implementations, but with a huge responsibility towards backwards compatibility, because if JavaScript suddenly stops supporting a feature or changes semantics, we might find out that this is a corner case on which half of the Internet depends. In other words, the stakes are much, much higher than making some developers happy.¹⁹

A solution proposed by the ES5 folks was to introduce an optional mode into JavaScript that would limit what you can do, but be otherwise backwards compatible. I think this was a move in the right direction. For example, strict mode²⁰ does not let you assign to read-only variables or delete a prototype of class. Good stuff. On the other hand strict mode will not fix any of the problems I have listed above.

So what’s left but to exercise discipline and hope that the company which produced that module that your product is relying on didn’t hire any imprudent developers? Solutions can be found in the form of language extensions, or languages which compile into JavaScript. Projects like Typescript,²¹ Coffeescript,²² Amber.²³

Typescript introduces compile-time typing to prevent bugs, Coffeescript removes Java-like syntax from JS in order to make it more FP-like and Amber is a dialect of SmallTalk that transpiles into JS (therefore avoiding JS syntax entirely).

While these projects are steps in the right direction, I think there are problems that such languages don’t address. Let’s go over them.

Typescript. While it has an amazing user base and many JS projects now have typing to make them compatible with TS, it won’t stop you from running into many runtime issues. This is due to the TS philosophy of never affecting the runtime, only giving compile-time information. An example of this may again be the dreaded NaN% displayed on your website.

Coffeescript. While it does what it says on the can — removes Java syntax from JavaScript, it also adds a few surprising features. For example there are infix conditions like doSomething() if condition == true, and the character @ instead of the accessor this. This is problematic, since most mainstream developers wouldn’t be comfortable with such alien syntax. Worse still, CoffeeScript won’t protect you from the dreaded NaN% displayed on your website either 😃

Amber. While SmallTalk is a very popular language in certain circles (universities come to mind), it’s a small community. Amber, being a dialect of that arcane language, suffers from this since it has very little community support. As such, it’s very hard to find out a lot about it or to use it professionally.

Amber will actually protect you from the dreaded NaN% problem though! But by crashing and displaying an error message. This is inappropriate, as it may prevent the user from seeing any content on your site at all.

What am I doing about it?

So, I decided to develop my own language. I named it JonScript, since my name is Jon and it compiles into JavaScript. JonScript does something different. It combines types from Typescript, functional programming from Coffeescript and works on fixing the long-present problems with JavaScript operators and standard API.

Important thing to consider is that JonScript uses typing not just as compile-type help, but to affect the behavior of the language at runtime. Because of this type-dependency, JonScript needs TS packages only. Since Typescript is wildly popular²⁴ and many household JS packages are compatible with TS, this should not be a problem.

Here are the guiding principles for JonScript:

  1. Consistency: Only one way to do things;
  2. Compatibility: Use Typescript libraries and use Typescript code; and
  3. Usability: Current JavaScript developers should be able to quickly understand the language.

Next, let’s discuss the main features of JonScript, and why I think it’s a good idea for you to get familiar with it. Keep in mind that JonScript is in its alpha stage — it’s hardly ready for full production. Still, it works and you can already write in it. If you want to try out JonScript for yourself, download the npm package jonscript (link) and then set up a basic webpack³⁰ build like this:

const path = require(“path”);
module.exports = {
entry: {
“jons”: “./src/index.jons”,
“index”: “./src/index.ts”,
},
mode: “development”,
module: {
rules: [
{
test: /\.jons$/,
use: “jonscript”,
exclude: /node_modules/,
},
{
test: /\.tsx?$/,
use: “ts-loader”,
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [ “.tsx”, “.ts”, “.js”, “.jons” ],
},
output: {
filename: “[name].js”,
path: path.resolve(__dirname, “dist”),
},
};

This will compile JonScript into TS files. All you need to do next is import them from the jons-temp folder and run the app. If the build fails the first time, try again — webpack might not have noticed JonScript files being parsed. I will fix this ASAP.

Next, let’s take a look at JonScripts most important features:

Just one kind of function

All functions created or executed within JonScript will behave like arrow functions. This is done by detecting functions during compilation and binding their execution context automatically. This includes standard API functions and all imported functions from any module.

Module {
TestClass() {
privateProperty: [1, 2, 3, 4],
// .map function will be bound to privateVariable
privateMethod: privateProperty.map,
{
publicMethod: () => privateMethod(i => i + 1),
}
}
}

While this can break legacy packages which rely on this behaviour, there is a solution. JonScript allows for imports from TS files. This means that JonScript will not restrict you from using standard JavaScript features — it merely tries to guide you to a safer and better path.

Just one kind of null

All nulls and NaNs are converted into one type: undefined. Undefined values will be converted into empty strings during concatenation. All null-value keys are deleted from the object. And, due to fixes in operators discussed further below, you don’t ever need to worry about undefined properties lingering and showing up on your website. The undefined value exists as the “nil” primitive. Similarly, the “void” type TS developers know also simply becomes “nil”.

Here’s how that looks in practice:

Module {
TestClass() {
{
// Converts NaN into undefined
publicMethod: () => (0 / 0),
// Returns simply “%”
otherPublicMethod: () => publicMethod() + “%”,
}
}
}

Pattern matching operator

JonScript introduces a new binary operator is. The is operator effectively acts as a replacement of both typeof and instanceof, but it’s more than just that. It also serves as a way of type coercion, similar to the is predicate in Typescript.

First, let’s talk about the difference between instanceof and typeof in JS and why I removed them:

  • typeof is a unary prefix operator which returns the type of a variable.
    It can return either “undefined”, “string”, “number”, “bigint”, “object”, “function”, or “symbol”. You might notice that array and null are missing from the list — they are both objects. What about Number and String classes? Well, they are also objects. To find out about what an object actually represents, you have to do further checks.
typeof null === “object”
/* and */
typeof [] === “object” /* is true */

This also leads to unintuitive distinctions:

typeof 2 === “number”
/* is true */
typeof new Number(2) === “number” /* is false */
  • instanceof is a binary infix operator which tries to access the __proto property of an object. This is how JS determines to which class an object belongs.
[1, 2, 3] instanceof Array
/* is true */
2 instanceof Number /* is false */
  • This is pretty strange. Why is number not an instance of Number?! This is even stranger, since you can call methods on primitives! Turns out that instanceof will only work on function and object types.

Now that you know how JS does type checks, now let’s talk about is predicates in TS.

The is predicate in TS acts as a type guard. You use it instead of the return type of a function. The function must return a boolean value. When this function is executed in a condition, Typescript considers the parameter passed into the function as being coerced.

const isFish(
pet: Fish | Bird
): pet is Fish => (pet as Fish).swim !== undefined;
let pet = getSmallPet();// Both calls to ‘swim’ and ‘fly’ are now okay.
if (isFish(pet)) {
pet.swim();
} else {
pet.fly();
}

Source: https://www.typescriptlang.org/docs/handbook/advanced-types.html.

JonScript combines the functionality of typeof, instanceof and is into a single operator. It does both type coercion and it works with both primitives and classes on the same level. But it gets even better — a pattern matching algorithm is used to make JonScript even more powerful than just a combination of the above. I don’t want to get into the details of this algo here since it gets a little complex. So in order to showcase what JonScript can match, here is a small taste of its pattern matching:

Module {
TestClass() {{
value1: 2,
value2: “Hello”,
value3: {{ value1, value2 }},
pattern1: Number,
pattern2: String,
pattern3: {{ value1: Number }},
pattern4: {{ value2: String }},
pattern5: {{ value2: Number }},
results: [
value1 is pattern1, // true
value2 is pattern2, // true
value3 is pattern3, // true
value3 is pattern5, // false
value2 is pattern1, // false
],
}}
}

The is implemented using a library called matchto.²⁹ NPM uses a versioning system to ensure no random update to this library will change the behavior of JonScript.

Automatic new keyword insertion

Typescript can determine whether a call to a function has a class signature. We use this to simplify the language syntax in order to insert the new keyword so that JonScript developers don’t need to.

This has actual benefits for the runtime as well: according to the test, most JS developers assume that new keyword is simple syntactic sugar. This is wrong.

For example, calling Date() and new Date yields different results. If you are wondering why there are no parentheses when calling new Date, you can probably agree that removing the new keyword from the language is beneficial.

Automatic async keyword insertion

We use Typescript to check if an expression returns a promise. We use this to simplify language syntax in order to insert the async keyword wherever it is needed. JonScript doesn’t even need that keyword in its syntax.

Async ensures that whatever value is returned from a function takes the form of a Promise. This makes promise usage in JonScript much safer:

Here you can see an example of a function that may crash in JS, if you try to use promise callback:

const funct = (i) => i > 5 ? 5 : new Promise(then => then(5));

One kind of class

JonScript has one one kind of class and one kind of inheritance — prototypal inheritance. It does not utilize the prototype object used in JS. Instead, it analyzes the typing of expressions from which a class, or an object inherits and defines appropriate local variables, whose values are then added as public properties of the class. Here’s a simple example:

// imports a class with single public property of “a”
import { parentClass } from ”./parentClass”
Module {
TestClass() {
privatePropertyOfClass: 5,
…parentClass(), // TestClass inherits from parentClass
{
publicMethod: () => {
privatePropertyOfObject: ”Hello”,
{
// 1, 2 property “a” from parentClass
publicPropertyOfObject: [1, 2, a],
}
},
// You can also access “a” from instance of TestClass
}
}
}

Easy recursion

This feature is a bonus for experienced Typescript developers. JonScript allows for a recursive type definition of all JonScript objects and classes.

Module {
TestClass() {{
publicObject: {{
publicObjectProperty: 5,
}},
publicMethod: (parameter: Class<TestClass>) => parameter,
anotherPublicMethod: (
parameter: Object<publicObject>
) => parameter,
}}
}

Forgiveness done right

Similar to JavaScript, JonScript is a forgiving language, but better. Accessing, calling, doing addition etc. on nil values results in a simple nil value (except for concatenation — nil + “Hello” results in “Hello” string). All incompatible operations, for example, comparing string with number, subtracting string from number etc. results in nil as well.

Operator overloading and sensible coercion

We know that JS operators are strange. When implementing JonScript, one of the goals I had in mind was: if you use an operator on a class (like String or Number), you should get a class back — in JavaScript, string concatenation containing String class objects results in a string primitive. This is more consistent and intuitive.

Undefined operations such as subtracting strings, multiplying objects or using modulo on an array should return undefined (nil in JonScript). Similar to JS, JonScript uses the + operator as both concatenation and addition.

JonScript supports operator overloading. The overload is done by defining one of these methods on an object or class: plus, minus, divide, multiply, module or compare (for comparison operations, return 0 if objects are equal, greater than 0 if left is bigger than right, less than zero if opposite). All overload methods must be defined with a single parameter.

Operator overloads work both on the left and right hand side:

overloaded + “hello” /* same as */ “hello” + overloaded

There is one exception. When using two objects with overloads, the left hand side is applied. Down below is a table of arithmetic operations and resulting types. Switching left-hand side and right-hand side won’t affect the type of result. The string/String and number/Number terms in the table denotes the difference between string and number primitives and their class counterparts.

Table of arithmetic operations

Next, let’s talk about comparison operators. They have similar common-sense rules. There is a limited amount of coercion: you can compare string/String and number/Number and get results as if comparing two primitives. Cross comparison between string and number will always result in false. Any object comparison, besides expected equality, will always result in false as well.

Operator overloading for comparison works in the same way as it does with arithmetic operations. Equality and non-equality of objects is decided in the same fashion as it is in JavaScript (pointer comparison).

What still needs doing?

So that’s JonScript.

I wish I had an infinite amount of time and resources to push JonScript to perfection. Sad reality is that an alpha version of JonScript still has a long way to go. Here are its problems:

Will fix

These issues/features were not added to JonScript only due to time constraints. I will be shipping them with future versions of the language, or they will be shipped within a utility package.

Insufficient escaping in interpolated strings

In order to escape the characters “$”, “{” or “}” in interpolated strings, you need to use “\”. In plain JS, you only need to escape “$”. This will be fixed in future versions with better parsing.

No JSX support

Future versions of JonScript will contain full JSX²⁶ support and default React import.

Insufficient fixes of standard api

While there are fixes in typing and execution of Object.keys, values and entries and Array.push method, this is by no means a complete fix of std. API. Future versions will contain more comprehensive fixes. These fixes are guaranteed to only affect the execution of code directly in JonScript as to not break compatibility with TS libraries.

Map files

Map files allow programmers to debug transpiled code by mapping it back to the original. Future versions of JonScript will include a map file generator compatible with webpack.

Visual Studio Code extension

Visual studio code is an open source, extensible IDE developer by Microsoft. A JonScript extension will be rolled out in the future. Most important features are: syntax highlighting, debugging and code references.

May fix

These issues require more research time than I have currently available. They may be fixed in future releases, depending on popular demand and whether or not it is possible to fix them. This list also includes problems with more than one possible solution.

Nullable types sometimes cause typing problems

Since there is null forgiveness within the language, TS will sometimes incorrectly interpret this forgiveness as possible null value and will throw an error. These errors can be avoided by either using a nullable type, or a null check. This will be fixed in future versions with either only forgiving explicitly nullable types or with every type in JonScript being nullable²⁵.

Is operator unable to match objects to prototypal classes

As discussed previously, JonScript uses exclusively prototypal inheritance. This creates an interesting problem: Imagine trying to use an operator like instanceof on a prototypal inheritance system. Each class can have multiple parents and each parent can override other parents properties and methods. Each class can also remove/override parents’ methods. You can, therefore, build a class which has none of its parents’ methods.

There is little value in figuring out whether an object is of a certain class because of this. While the is operator does support instanceof operations, the same support is not extended to JonScript classes. Instead, you can simply use a property of a class as an indicator to be used during pattern matching. This may change in the future.

// Can't do this yet
testClassInstance is TestClass
// But CAN do this - and Typescript will take care of rest
testClassInstance is {{ testProperty: "correctValue" }}

The build process needs optimization

There is a lot of room for improvement in how long the build process takes. There is a severe slowdown in compilation when using class inheritance that I will be addressing in the future.

Won’t fix

These issues have something to do with the JS engine, compatibility, or execution speed. It’s not likely that I’ll be able to fix these.

No deep object sanitization

When creating an object in JonScript, you have a couple of guarantees — recursive typing, no null-value keys.²⁷ When importing an object from outside of JonScript, you don’t have recursive typing, nor direct sanitization. This is done for both compatibility and performance reasons. However, if you use a property from an object, this property will be automatically sanitized.

Subtle differences between primitives and their class counterparts²⁸

While the class Boolean is removed from JonScript, completely — and for a good reason:

new Boolean(false) == false
/* is true, but: */
!new Boolean(false) /* is false!!! */

classes of String and Number have gained additional usage — with operator overloading and pattern matching. You need to be careful however: String class of empty string and Number class of zero are not falsy, while their primitive counterparts are. It is also impossible to overload properties of primitive values, such as boolean, string or number (or use them in inheritance).

Conclusion

There is a lot of work to be done. There is a lot of work already done. JonScript allowed me to explore the depths of JavaScript. I hope this article was helpful to any developer that seeks to gain a better understanding of JS, and an alternative to JS. I hope I convinced you that JonScript is an interesting project and that it has future potential. Maybe you’ll give it a try!

JonScript is a part of my Master’s Thesis. When I finish working on it, I’ll add a link to it here for more information.

Footnote 1:
Cynthia Lee. When (and why) you should use ES6 arrow functions — and when you shouldn’t. https://www.freecodecamp.org/news/when-and-why-you-should-use-es6-arrow-functions-and-when-you-shouldnt-3d851d7f0b26/

Footnote 2:
Juan Cruz Martinez. When not to use JavaScript Functions. https://livecodestream.dev/post/when-not-to-use-javascript-arrow-functions/

Footnote 3:
Andrew Koenig-Bautista. 3 Examples of When Not to Use JavaScript Arrow Functions
https://betterprogramming.pub/3-examples-of-when-not-to-use-javascript-arrow-functions-90eebfbf7bb0

Footnote 4:
Dmitri Pavlutin. When ‘Not’ to Use Arrow Functions.
https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/

Footnote 5:
Dmitri Pavlutin. 5 Differences Between Arrow and Regular Functions.
https://dmitripavlutin.com/differences-between-arrow-and-regular-functions/

Footnote 6:
Dmitri Pavlutin. 5 Best Practices to Write Quality JavaScript Variables. https://dmitripavlutin.com/javascript-variables-best-practices/

Footnote 7:
Yash Agrawal. Declaring Variables in ES6+ JavaScript. https://codeburst.io/declaring-variables-in-es6-javascript-60ea37e38765

Footnote 8:
Chris Nwamba. Declaring JavaScript Variables: var, let and const
https://scotch.io/courses/10-need-to-know-javascript-concepts/declaring-javascript-variables-var-let-and-const

Footnote 9:
Dhananjay Kumar. Creating objects in JavaScript (4 Different Ways).
https://www.geeksforgeeks.org/creating-objects-in-javascript-4-different-ways/

Footnote 10:
Ashutosh K Singh. Three Different Ways to Create Objects in JavaScript.
https://betterprogramming.pub/three-different-ways-to-create-objects-in-javascript-d3595d693296

Footnote 11:
https://twitter.com/BrendanEich/status/771006397886533632

Footnote 12:
localtime(3)
https://linux.die.net/man/3/localtime

Footnote 13:
Minko Gechev. JavaScript, the weird parts.
https://blog.mgechev.com/2013/02/22/javascript-the-weird-parts/

Footnote 14:
Standard ECMA-262. 5.1 Edition / June 2011. ECMAScript® Language Specification. Section 11.8: relational operators.
https://262.ecma-international.org/5.1/#sec-11.8

Footnote 15:
Typeof operator docs
https://developer.mozilla.org/en-US/docs/Web/Javascript/Reference/Operators/typeof

Footnote 16:
Instanceof operator docs
https://developer.mozilla.org/en-US/docs/Web/Javascript/Reference/Operators/instanceof

Footnote 17:
Why not to use classes
https://everyday.codes/javascript/please-stop-using-classes-in-javascript/

Footnote 18:
Prototypal inheritance in JavaScript
https://www.educative.io/blog/understanding-and-using-prototypal-inheritance-in-javascript

Footnote 19:
Richard Kenneth Eng. JavaScript cannot be fixed!
https://medium.com/javascript-non-grata/as-others-have-noted-the-fundamental-problem-with-web-development-is-that-javascript-is-a-broken-7f9675048c77

Footnote 20:
Aphinya Dechalert
https://dottedsquirrel.com/javascript/how-javascript-still-hasnt-broken-the-internet-just-yet/

Footnote 21:
Typescript
https://www.typescriptlang.org/,

Footnote 22:
Coffeescript
https://coffeescript.org/

Footnote 23:
Amber
https://www.npmjs.com/package/amber

Footnote 24:
Typescript popularity
https://venturebeat.com/2020/12/02/github-python-and-typescript-gain-popularity-among-programming-languages/

Footnote 25:
Advanced typescript types
https://www.typescriptlang.org/docs/handbook/advanced-types.html

Footnote 26:
React
https://reactjs.org/docs/introducing-jsx.html

Footnote 27:
Examples of problems within JS object structure
https://dmitripavlutin.com/check-if-object-has-property-javascript/

Footnote 28:
Differences between String and string
https://developer.mozilla.org/en-US/docs/Web/Javascript/Reference/Global_Objects/String

Footnote 29:
Matchto library
https://www.npmjs.com/package/matchto

Footnote 30:
Webpack
https://www.npmjs.com/package/webpack

--

--