JS++ is seamlessly compatible with all JavaScript libraries, frameworks, and APIs (such as the Document Object Model API for scripting the web browser).
Compile times are a very important part of the user experience for JS++. By using traditional nominal typing, existent types avoid following every branch, loop, virtual method call, and other complexities that can cause compile times to exponentiate or – in the worst case – run into the Halting Problem.
When used correctly, existent types will prevent the application from terminating prematurely via abort(), segfaults, uncaught exceptions, runtime errors, etc.
JAXenter: Does TypeScript prevent out-of-bounds errors?
Roger Poon: No, a lot of languages can’t. However, in our latest benchmarks, we showed that you can compile 6,000 lines of JS++ code across 70 files – with sound type checking and full analysis of out-of-bounds errors – four times over in the time it takes TypeScript to compile 3 lines of code and get the types wrong. Here’s the TypeScript code and proof:
$ ./node_modules/typescript/bin/tsc --version
Version 3.2.2
$ cat test.ts
const xs: number[] = [1,2,3];
let x:number = xs[1000]; // number... even with --strictNullChecks
console.log(x);
$ time ./node_modules/typescript/bin/tsc --strictNullChecks test.ts
real 0m1.084s
user 0m1.692s
sys 0m0.016s
$ node test.js
undefined
However, it should be said that out-of-bounds errors have existed since the first high-level programming language, Fortran, and continues to be a problem today.
In contrast, in the latest release of JS++, here are our compile times with out-of-bounds error analysis:
JAXenter: JS++ is described as having “nearly no learning curve.” Can you elaborate on this?
Roger Poon: Once you learn “internal types” (JS++ types), “external types” (JavaScript types, although technically it describes more), and the conversions between them, the rest of JS++ should be intuitive for programmers with backgrounds in C, C++, Java, and C#.
For example, function overloading in JS++ is what you would expect: multiple function declarations with the same name. In TypeScript, users run into surprises where one function body handles all constructor overloads. Furthermore, JS++ has 8-, 16-, 32-, and 64-bit signed and unsigned integer types, so there aren’t any ‘NaN’ surprises that arise when all your numbers are IEEE-754 doubles as in JavaScript/TypeScript.
SEE ALSO: Pluralsight 2018 wrap-up: JavaScript reigns supreme, Dart gains momentum
JAXenter: Can you describe the migration path from JavaScript to JS++?
Roger Poon: Due to its advanced type system, JS++ can be one cog in a larger system. There is no vendor lock-in. For example, your JS++ commitment can be one file, one class, one module, one project, or even one line of code. JS++ is backwards- and forwards-compatible with JavaScript. It is designed to be seamlessly compatible with the rest of your system whether it’s JavaScript, TypeScript, etc – without vendor lock-in.
In contrast, TypeScript requires steep commitment due to its unsound type system. Before you can reap the full benefits of TypeScript, you have to add “typings” to almost all your code before it’s able to perform meaningful analyses. One company described their migration of 30,000 lines of JavaScript to TypeScript, and their independent conclusions were:
- You can’t always trust the compiler
- Type inference doesn’t go very far
- TypeScript requires many type annotations
- Types are still your assumptions
- Typing can’t always be incremental
- Circular dependencies
All of the problems listed above (except circular dependencies) are side effects of an unsound type system – everything from being unable to trust the compiler to requiring lots of type annotations before the tool becomes useful. It needs to be re-emphasized that JS++ can start becoming useful with one type annotation. We do not require you to rewrite your entire code base. They specifically highlighted that TypeScript failed incrementally (so you’re not going to just use it on 1% of a 1 million line code base), required many type annotations before it became useful (again, you’re not going to use it on 1% of your code successfully – even though technically you can, and Microsoft will tout this as a win without discussing the theoretical concerns), the risk of human error (e.g. I can declare a string but accidentally tell TypeScript it is a number), and so on.
An investment into TypeScript means accepting all the problems – now and in the future – that could have been avoided by choosing JS++
The problems they faced with the TypeScript compiler and type system don’t just grow linearly. Logically, they would exponentiate at scale if you think A is a number (but it’s actually a string at runtime) and the variables B, C, D, E depend on A and have further dependencies themselves.
It’s also interesting to note how they were bitten by a TypeScript breaking change:
“TypeScript doesn’t allow circular dependencies. Sort of. TypeScript was happily compiling our code, circular dependencies and all, for months until one day it broke.”
Despite having reached version 1.0 nearly 5 years ago, Microsoft TypeScript still routinely makes breaking changes on each new release. Meanwhile, JS++ automatically handles circular dependencies, automatically resolves complex cross-file import and inheritance hierarchies, and almost never makes breaking changes. I provide an explanation of the engineering behind how we efficiently handle circular dependencies – even in the presence of ambiguities – here.
In JS++, you don’t need to figure out all the types in your existing code. You only need to add types going forward in your new code or incrementally add types one-by-one to your existing code. Our Getting Started guide teaches both these techniques. You can also write a library in JS++ that can be consumed in JavaScript, and the types that you declared by writing the library in JS++ will be “preserved” even though you’re using the library from JavaScript via the toExternal/fromExternal design pattern. Finally, you can import an entire JavaScript library to JS++ using the external statement.
As a consequence, JS++ can be used in one file, one library, one class, one module or scale to your entire project. Thus, since JS++ works so well from the smallest commitment to the largest commitment, there is almost no vendor lock-in and no future risk of vendor lock-in.
Thank you!