1. Introduction

This book will introduce the JS++ type system. The type system in JS++ is one of its most distinguished and unique features. Learning the JS++ type system is critical to mastering the JS++ programming language.

This book covers materials that range from the beginner level, such as declaring typed variables, to advanced design patterns. We try to break down advanced engineering and theoretical concepts as much as we can. Feedback is always welcome; just email me at roger at roger dot net.

If you take pride in delivering the highest-quality software, you need to read this book and try your best to understand it from start to finish.

1.1. Programs have Data; Data have Types

Programs contain data. This data can be in the form of numbers, text, JSON, and so on. All data have types, commonly known as the "data type" or just "type" for short. For example, text is often represented with a "string" type. Numbers may be represented by types like "int" or "double".

Why is it important to have types? Without types, all kinds of errors can happen. For example, how would one logically subtract two texts (strings)? It's impossible, and it should be an error. Likewise, functions can be called, but what if the callee was not a function but a number? Again, this is an error.

Generally, there are two distinct typing disciplines: dynamic typing and static typing. In dynamic typing, the types are determined at runtime when you run the application. In static typing, the types are determined at compile time—before the program ever runs. However, there is no such thing as being "untyped." Programs have data, and data have types! JavaScript is dynamically-typed (typed at runtime) while JS++ is statically-typed (typed at compile time). Why is this distinction important? It means - in JavaScript - your program can have type errors at runtime; in JS++, before you ever run your program, all type errors must be resolved.

In JavaScript, programs will simply keep running with errors, causing errors to creep and propogate across the application. Recall that - even in JavaScript - there is no such thing as "untyped" (or no types). Data have types. In dynamic typing, you are simply having to keep track of all the types in your head. This is fine for one or two lines of code, but as applications grow in complexity, this can happen:

var a = 1;
var b = "abc";

// Hundreds of lines later...
var subtotal = a - b; // NaN
document.write("Your subtotal is: " + subtotal); // Your subtotal is: NaN

Yet, JavaScript isn't totally forgiving. Some errors can actually crash the script:

// Simple variable declaration. Innocuous, right?
var a = typo; // ReferenceError: typo is not defined

console.log("Script started"); // Never runs. Script already crashed with ReferenceError.

In certain static type systems, even though values can change often, the types remain consistent. Thus, even if we generate two random numbers, it does not matter if we are subtracting 1, 2, 3, 5000, etc. The type remains the same: it's always a number type, and subtraction is valid on numbers. Types remaining unchanged can be illustrated as follows:

int x = 1; // Variables - by definition - vary. However, their types always remain the same.
x = 2;     // Data changes. Type remains the same.
x = 3;     // Data changes. Type remains the same.
x = "a";   // Data changes. We tried to change the type, but there is no valid conversion. Error.

In static typing, errors happen at compile time. Compile-time errors must be fixed; otherwise, the program doesn't compile. If a program doesn't compile, there is no program to run. Therefore, a program that might crash from a type error never actually runs... because it never compiled to begin with.

Even with programs that are highly-dynamic, such as programs that behave differently on each run due to random number generation, the types remain the same. Since the types remain the same, we can apply logic and mathematics to prove that a program is correct and is free of type errors—before it ever runs! This is the essence of static typing. We want full confidence that our Node.js server will not crash from a single typo or that our shopping cart will not produce NaN (Not a Number) error values before we ship it. Whether you're writing ten lines of code or 100,000 lines of code, static typing allows you to build high-quality applications. It's the same tool that experienced, battle-hardened software engineers use to ship high-quality, commercial and industrial software from banking to rocketry.

1.2. Sound Type Systems

We will briefly discuss the notion of logical "soundness." Soundness is based on "truth." In other words, if a type system is sound, the types you declare will never be incorrect. (Note that in JS++, you don't have to declare types, which we will discuss.) If a type system is unsound, you can declare a string that, at runtime, turns into a number.

The JS++ type checker implements the first type system that enables static typing but is able to consume a dynamically-typed language (in this case, JavaScript) while remaining sound. Thus, a string will always remain a string, an unsigned int will always remain an unsigned int, and an object based on an Employee class will always remain an Employee object. This is what is meant when you hear that JS++ solved the computer science problem of soundly consuming dynamically-typed code from a statically-typed programming language—the types you declare are simply never incorrect and will always be correctly preserved.

Consider the following code:

var func:any = function() {};

var str1:string = func;
var str2:string = str1.toLowerCase(); // TypeError: undefined is not a function

console.log(str2); // Never runs. Program already crashed from TypeError.

The above code illustrates what can happen when a programming language's type system is unsound. str1 was declared as a string but became a function at runtime. Likewise, str2 - which depends on str1 - crashes. The compiler trusted str1 to be a string even though it wasn't and permitted the method toLowerCase (a method exclusive to strings) to be called. However, since str1 was actually a function, which doesn't have a toLowerCase method, the application crashes at runtime.

In JS++, the declared types are correctly preserved even when introducing the erratic behavior of JavaScript. Whether a feature was implemented differently in one browser to another, an ActiveX was introduced, Object.prototype was overwritten using V8's C++ API (and thus the overwriting is never exposed to JavaScript itself), the types you declare with JS++ are guaranteed to always remain correct. Because, ultimately, why would you declare thousands of types when your strings can become numbers, functions, or nulls on every tenth run of the application? Soundness matters.

1.3. Optional Typing

In JS++, you are not required to declare types for your variables and functions. The types are only guaranteed to be correct if and only if you specify a type. If you write your JS++ code with var and function as you would in JavaScript, you are not guaranteed to benefit from type safety. However, if you change your var into a string, you are guaranteed to always get a string.

("Adding types" to JavaScript might sound simple on the surface, but this was surprisingly difficult to get right - especially to get it logically sound. See Appendix B which discusses why simply "adding types" to JavaScript was such a difficult problem to solve.)

Ultimately, the hope is that you will gradually and incrementally add types to your JavaScript code. Thus, you can "migrate" a JavaScript program from 0% typed to 100% typed. Especially in complex web applications that exceed one million lines of JavaScript code, having the complete confidence that one change to the type of a single variable or function, guaranteed to always be correct, will empower you to take the first small steps in the daunting task of upgrading complicated code. However, the JS++ type system will benefit developers working on projects large and small by helping to deliver higher quality with some simple changes. Let's get started...