WhyStaticTypeCheckingisBetter
@AndrewRota
JavaScript Engineer,
With JavaScript...anything is possible
@AndrewRota | #empirejs 2/48
Change all the types...
@AndrewRota | #empirejs
var x; // x starts undefined
typeof x === 'undefined'
x = 5;  // now it's is a number
typeof x === 'number'
x = 'five'; // now it's a string
typeof x === 'string'
x = true;  // now it's a boolean
typeof x === 'boolean'
x = {value: 'five'}; // now it's an object
typeof x === 'object'
JS
3/48
We have types, but they're not static.
(No type is known or declared at compile time)
@AndrewRota | #empirejs 4/48
7 Types in JavaScript
@AndrewRota | #empirejs
Boolean Number String Object
Symbol Null Undefined
5/48
Most code has type expectations
...we just don't always acknowledge it.
@AndrewRota | #empirejs
function add(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
add([2,3]); // returns 5 as expected
add(['foo', 'bar']);  // returns "0foobar" (expected?)
add(null);  // Throws exception: cannot read prop 'length' of null
JS
6/48
What to do?
@AndrewRota | #empirejs 7/48
Ad Hoc Runtime Checks
@AndrewRota | #empirejs
function add(arr) {
    if (!Array.isArray(arr)) return;
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        if (typeof arr[i] !== 'number') return;
        sum += arr[i];
    }
    return sum;
}
JS
8/48
Ad Hoc Runtime Checks
@AndrewRota | #empirejs
function add(arr) {
    if (!Array.isArray(arr)) throw('not an array');
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        if (typeof arr[i] !== 'number') throw('not a number');
        sum += arr[i];
    }
    return sum;
}
JS
9/48
Type Annotations
@AndrewRota | #empirejs
/**
 * Add all numbers in an array
 *
 * @param {number[]}
 * @return {number}
 */
function add(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
JS
10/48
Type Annotations
Explicit typing...without any checks.
@AndrewRota | #empirejs
/**
 * Add all numbers in an array
 *
 * @param {number[]}
 * @return {number}
 */
function add(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
JS
11/48
Code Reviews !== Type Checks
@AndrewRota | #empirejs 12/48
Type Checking in JavaScript
@AndrewRota | #empirejs 13/48
ActionScript
Early 2000s | Partially conformed to ECMAScript 4
@AndrewRota | #empirejs
private function add(arr:Array):int{
    var sum:int = 0;
    for (var i:int = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
AS
14/48
Closure Compiler
~2009
@AndrewRota | #empirejs
/**
 * Add all numbers in an array
 *
 * @param {number[]}
 * @return {number}
 */
function add(arr) {
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
JS
15/48
TypeScript
2012 | Compiles to JavaScript, optional static typing
@AndrewRota | #empirejs
function add(arr:Array<number>):number{
    var sum:number = 0;
    for (var i:number = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
TS
16/48
Flow
2014 | Compiles to JavaScript, optional static typing
@AndrewRota | #empirejs
/* @flow */
function add(arr:Array<number>):number{
    var sum:number = 0;
    for (var i:number = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
FLOW
17/48
Flow Comments
2015 | Alternative to a transpile step
@AndrewRota | #empirejs
/* @flow */
function add(arr/*:Array<number>*/)/*:number*/{
    var sum/*:number*/ = 0;
    for (var i/*:number*/ = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}
JS
18/48
Released Runtime Env. No Transpile Null Checking ES6
Closure Compiler 2009 Java ✓ X Some
TypeScript 2012 JavaScript X X Some
Flow 2014 OCaml X ✓ Some
Flow Comments 2015 OCaml ✓ ✓ Some
@AndrewRota | #empirejs 19/48
Adding Gradual Type Checks
@AndrewRota | #empirejs 20/48
Step 1: Choose a Type Checker
Step 2: Set Up a Transpile Step
Step 3: Add Type Annotations
@AndrewRota | #empirejs 21/48
Step 1: Choose a Type Checker
Step 2: Set Up a Transpile Step
Step 3: Add Type Annotations
@AndrewRota | #empirejs 22/48
TypeScript Flow
TypeScript vs. Flow
@AndrewRota | #empirejs
Released 2012
Written in JS: any OS
Community-provided
declaration files
Addtional transpiled features
(defaults, overloads)
·
·
·
·
Released 2014
Written in OCaml: OSX, Linux
Built-in null handling.
Comment-only syntax
available
·
·
·
·
23/48
Step 1: Choose a Type Checker
Step 2: Set Up a Transpile Step
Step 3: Add Type Annotations
@AndrewRota | #empirejs 24/48
Setting Up Flow
1. Install Flow from flowtype.org
2. Add transformer ( JSX or Babel ) to your build
@AndrewRota | #empirejs 25/48
Using Flow
1. Run flow check
2. Run build with transformer.
@AndrewRota | #empirejs
Check → Transform
26/48
Using Flow
@AndrewRota | #empirejs 27/48
Setting Up TypeScript
Install TypeScript with npm i ‐g typescript
@AndrewRota | #empirejs 28/48
Using TypeScript
Run tsc myFile.ts
@AndrewRota | #empirejs 29/48
Using TypeScript
@AndrewRota | #empirejs 30/48
Step 1: Choose a Type Checker
Step 2: Set Up a Transpile Step
Step 3: Add Type Annotations
@AndrewRota | #empirejs 31/48
Type Inference
Some of your work's already done!
Flow: property length: Property not found in Number
TypeScript: Property 'length' does not exist on type 'number'
@AndrewRota | #empirejs
var x = 1;
x.length;
JS
32/48
Adding Basic Types
Flow: number, string, boolean, void, Array, Function, Object, mixed, any
TypeScript: number, string, boolean, void, Array, Function, Object, any, enum
@AndrewRota | #empirejs
var x:string = 'test'; TS/FLOW
33/48
Arrays
@AndrewRota | #empirejs
var list:number[] = [1,2,3];
var anotherList:Array<number> = [1,2,3];
TS/FLOW
34/48
Union Types
ThisType | ThatType
@AndrewRota | #empirejs
var x: number | string = 0;
x = 'foo';
TS/FLOW
35/48
Null Checks
Flow has the advantage here
Flow: property x: Property cannot be accessed on possibly null value
TypeScript:  no error
@AndrewRota | #empirejs
var x = null;
x.foo;
JS
36/48
Functions
Both arguments and return values (the function itself)
@AndrewRota | #empirejs
function helloWorld(name: string):string {
   return 'Hello, ' + name;
}
function addExclamation(sentence: string):string {
    return sentence + '!';
}
addExclamation(helloWorld('EmpireJS'));
TS/FLOW
37/48
Object Literals
@AndrewRota | #empirejs
function doSomething(modelObject: {title: string}) {
   return modelObject.title;
}
doSomething({title: 'My Object!', id: 2, flag: true});
TS/FLOW
38/48
Interfaces
External interfaces via declaration files
→ Find TypeScript declarations at definitelytyped.org
@AndrewRota | #empirejs
interface Model {
    title: string
}
function doSomething(modelObject: Model) {
   return modelObject.title;
}
doSomething({title: 'My Object!', id: 2, flag: true});
TS/FLOW
39/48
And there's more!
@AndrewRota | #empirejs
Classes
Modules
Nullable Types
Generics
Polymorphism
·
·
·
·
·
40/48
But is it worth it?
@AndrewRota | #empirejs 41/48
Catch More Bugs at Compile Time
Flow: null: This type is incompatible with string
@AndrewRota | #empirejs
function helloWorld(name:string) {
    return 'Hello, ' + name;
}
helloWorld('EmpireJS');
helloWorld(null);
        
FLOW
42/48
Self-Document Code Behavior
@AndrewRota | #empirejs
function flatten (input, shallow, strict) {}
        
JS
function flatten (
    input: Array<any>,
    shallow: boolean,
    strict: boolean
): Array<any> {}
        
TS/FLOW
source: http://flowtype.org/docs/underscore.html#_
43/48
Easier to Reason About Code Flow
@AndrewRota | #empirejs
In: Number
Out: String
↗
In: String
Out: Object
↗
In: Object
Out: Boolean
44/48
- Bertrand Meyer
Correctness
“ The ability of software products to perform their exact tasks, as
defined by their specification.
@AndrewRota | #empirejs 45/48
Tooling
IntelliJ
Sublime
@AndrewRota | #empirejs 46/48
- TypeScript and the Road to 2.0
And someday it might be in JavaScript...
“ The TypeScript team is [...] looking forward to working together going
forward and creating the best tools we can for the JavaScript community.
In the long term, we will also be working to fold the best features of
these tools into ECMAScript, the standard behind JavaScript.
@AndrewRota | #empirejs 47/48
Thanks!
twitter @andrewrota
github github.com/andrewrota

Why Static Type Checking is Better

  • 1.
  • 2.
    With JavaScript...anything ispossible @AndrewRota | #empirejs 2/48
  • 3.
    Change all thetypes... @AndrewRota | #empirejs var x; // x starts undefined typeof x === 'undefined' x = 5;  // now it's is a number typeof x === 'number' x = 'five'; // now it's a string typeof x === 'string' x = true;  // now it's a boolean typeof x === 'boolean' x = {value: 'five'}; // now it's an object typeof x === 'object' JS 3/48
  • 4.
    We have types,but they're not static. (No type is known or declared at compile time) @AndrewRota | #empirejs 4/48
  • 5.
    7 Types inJavaScript @AndrewRota | #empirejs Boolean Number String Object Symbol Null Undefined 5/48
  • 6.
    Most code hastype expectations ...we just don't always acknowledge it. @AndrewRota | #empirejs function add(arr) {     var sum = 0;     for (var i = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } add([2,3]); // returns 5 as expected add(['foo', 'bar']);  // returns "0foobar" (expected?) add(null);  // Throws exception: cannot read prop 'length' of null JS 6/48
  • 7.
    What to do? @AndrewRota| #empirejs 7/48
  • 8.
    Ad Hoc RuntimeChecks @AndrewRota | #empirejs function add(arr) {     if (!Array.isArray(arr)) return;     var sum = 0;     for (var i = 0; i < arr.length; i++) {         if (typeof arr[i] !== 'number') return;         sum += arr[i];     }     return sum; } JS 8/48
  • 9.
    Ad Hoc RuntimeChecks @AndrewRota | #empirejs function add(arr) {     if (!Array.isArray(arr)) throw('not an array');     var sum = 0;     for (var i = 0; i < arr.length; i++) {         if (typeof arr[i] !== 'number') throw('not a number');         sum += arr[i];     }     return sum; } JS 9/48
  • 10.
    Type Annotations @AndrewRota |#empirejs /**  * Add all numbers in an array  *  * @param {number[]}  * @return {number}  */ function add(arr) {     var sum = 0;     for (var i = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } JS 10/48
  • 11.
    Type Annotations Explicit typing...withoutany checks. @AndrewRota | #empirejs /**  * Add all numbers in an array  *  * @param {number[]}  * @return {number}  */ function add(arr) {     var sum = 0;     for (var i = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } JS 11/48
  • 12.
    Code Reviews !==Type Checks @AndrewRota | #empirejs 12/48
  • 13.
    Type Checking inJavaScript @AndrewRota | #empirejs 13/48
  • 14.
    ActionScript Early 2000s |Partially conformed to ECMAScript 4 @AndrewRota | #empirejs private function add(arr:Array):int{     var sum:int = 0;     for (var i:int = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } AS 14/48
  • 15.
    Closure Compiler ~2009 @AndrewRota |#empirejs /**  * Add all numbers in an array  *  * @param {number[]}  * @return {number}  */ function add(arr) {     var sum = 0;     for (var i = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } JS 15/48
  • 16.
    TypeScript 2012 | Compilesto JavaScript, optional static typing @AndrewRota | #empirejs function add(arr:Array<number>):number{     var sum:number = 0;     for (var i:number = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } TS 16/48
  • 17.
    Flow 2014 | Compilesto JavaScript, optional static typing @AndrewRota | #empirejs /* @flow */ function add(arr:Array<number>):number{     var sum:number = 0;     for (var i:number = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } FLOW 17/48
  • 18.
    Flow Comments 2015 |Alternative to a transpile step @AndrewRota | #empirejs /* @flow */ function add(arr/*:Array<number>*/)/*:number*/{     var sum/*:number*/ = 0;     for (var i/*:number*/ = 0; i < arr.length; i++) {         sum += arr[i];     }     return sum; } JS 18/48
  • 19.
    Released Runtime Env.No Transpile Null Checking ES6 Closure Compiler 2009 Java ✓ X Some TypeScript 2012 JavaScript X X Some Flow 2014 OCaml X ✓ Some Flow Comments 2015 OCaml ✓ ✓ Some @AndrewRota | #empirejs 19/48
  • 20.
    Adding Gradual TypeChecks @AndrewRota | #empirejs 20/48
  • 21.
    Step 1: Choosea Type Checker Step 2: Set Up a Transpile Step Step 3: Add Type Annotations @AndrewRota | #empirejs 21/48
  • 22.
    Step 1: Choosea Type Checker Step 2: Set Up a Transpile Step Step 3: Add Type Annotations @AndrewRota | #empirejs 22/48
  • 23.
    TypeScript Flow TypeScript vs.Flow @AndrewRota | #empirejs Released 2012 Written in JS: any OS Community-provided declaration files Addtional transpiled features (defaults, overloads) · · · · Released 2014 Written in OCaml: OSX, Linux Built-in null handling. Comment-only syntax available · · · · 23/48
  • 24.
    Step 1: Choosea Type Checker Step 2: Set Up a Transpile Step Step 3: Add Type Annotations @AndrewRota | #empirejs 24/48
  • 25.
    Setting Up Flow 1.Install Flow from flowtype.org 2. Add transformer ( JSX or Babel ) to your build @AndrewRota | #empirejs 25/48
  • 26.
    Using Flow 1. Runflow check 2. Run build with transformer. @AndrewRota | #empirejs Check → Transform 26/48
  • 27.
    Using Flow @AndrewRota |#empirejs 27/48
  • 28.
    Setting Up TypeScript InstallTypeScript with npm i ‐g typescript @AndrewRota | #empirejs 28/48
  • 29.
  • 30.
  • 31.
    Step 1: Choosea Type Checker Step 2: Set Up a Transpile Step Step 3: Add Type Annotations @AndrewRota | #empirejs 31/48
  • 32.
    Type Inference Some ofyour work's already done! Flow: property length: Property not found in Number TypeScript: Property 'length' does not exist on type 'number' @AndrewRota | #empirejs var x = 1; x.length; JS 32/48
  • 33.
    Adding Basic Types Flow:number, string, boolean, void, Array, Function, Object, mixed, any TypeScript: number, string, boolean, void, Array, Function, Object, any, enum @AndrewRota | #empirejs var x:string = 'test'; TS/FLOW 33/48
  • 34.
  • 35.
    Union Types ThisType |ThatType @AndrewRota | #empirejs var x: number | string = 0; x = 'foo'; TS/FLOW 35/48
  • 36.
    Null Checks Flow hasthe advantage here Flow: property x: Property cannot be accessed on possibly null value TypeScript:  no error @AndrewRota | #empirejs var x = null; x.foo; JS 36/48
  • 37.
    Functions Both arguments andreturn values (the function itself) @AndrewRota | #empirejs function helloWorld(name: string):string {    return 'Hello, ' + name; } function addExclamation(sentence: string):string {     return sentence + '!'; } addExclamation(helloWorld('EmpireJS')); TS/FLOW 37/48
  • 38.
    Object Literals @AndrewRota |#empirejs function doSomething(modelObject: {title: string}) {    return modelObject.title; } doSomething({title: 'My Object!', id: 2, flag: true}); TS/FLOW 38/48
  • 39.
    Interfaces External interfaces viadeclaration files → Find TypeScript declarations at definitelytyped.org @AndrewRota | #empirejs interface Model {     title: string } function doSomething(modelObject: Model) {    return modelObject.title; } doSomething({title: 'My Object!', id: 2, flag: true}); TS/FLOW 39/48
  • 40.
    And there's more! @AndrewRota| #empirejs Classes Modules Nullable Types Generics Polymorphism · · · · · 40/48
  • 41.
    But is itworth it? @AndrewRota | #empirejs 41/48
  • 42.
    Catch More Bugsat Compile Time Flow: null: This type is incompatible with string @AndrewRota | #empirejs function helloWorld(name:string) {     return 'Hello, ' + name; } helloWorld('EmpireJS'); helloWorld(null);          FLOW 42/48
  • 43.
    Self-Document Code Behavior @AndrewRota| #empirejs function flatten (input, shallow, strict) {}          JS function flatten (     input: Array<any>,     shallow: boolean,     strict: boolean ): Array<any> {}          TS/FLOW source: http://flowtype.org/docs/underscore.html#_ 43/48
  • 44.
    Easier to ReasonAbout Code Flow @AndrewRota | #empirejs In: Number Out: String ↗ In: String Out: Object ↗ In: Object Out: Boolean 44/48
  • 45.
    - Bertrand Meyer Correctness “The ability of software products to perform their exact tasks, as defined by their specification. @AndrewRota | #empirejs 45/48
  • 46.
  • 47.
    - TypeScript andthe Road to 2.0 And someday it might be in JavaScript... “ The TypeScript team is [...] looking forward to working together going forward and creating the best tools we can for the JavaScript community. In the long term, we will also be working to fold the best features of these tools into ECMAScript, the standard behind JavaScript. @AndrewRota | #empirejs 47/48
  • 48.