Type Systems On The Web

Michael K Snead

Sr. Architect at Optimum Healthcare IT

Terms and Definitions

  • "Statically typed"
    Verifies types based on source code
     
  • "Dynamically typed"
    Checks type safety at runtime
     
  • "Strongly" (also "Strictly") or "Weakly" typed
    No universally accepted definition

Terms and Definitions

  • "Nominal types"
    If the name/position of the declaration is the same, it's a match.
    Two classes can be identical in every way, but are not a match because the name is different.
     
  • "Structural types"
    If all properties and methods match, it's the same type.
     
  • "Duck typing"
    "Establishing suitability for a given purpose"

Terms and Definitions

  • "Sound" (AKA "Provably Correct")
    A "sound" type system never permits an incorrect program to pass type checking.
     
  • "Unsound"
    An "unsound" type system makes trade-offs for a weaker/less expressive type system with the goal of gaining benefits such as increased productivity.

A brief look at the history of types in JavaScript...

June 2017

June 1997

In June of 1997, the first edition of JavaScript became a standard.

A brief look at the history of types in JavaScript...

June 2017

June 1997

June 1998

ES2

February of 1999

JavaScript 2.0 Draft by Waldemar Horwat at Netscape


  function foo(integer i) integer {
    return i + 1
  }

  public function Bar() {
    var a; // local to this function
    package var b; // package-visible global variable
    public var c; // public global variable
  }

  class Foo {
    public method Baz() { } // public class method
  }

  var any a; // "a" is type "any"
  var double b; // "b" is type "double"

A brief look at the history of types in JavaScript...

June 2017

June 1997

  
  function foo (i : Number) : Number { return 5; }
  print("Hi!")

  interface IBaz {
    function getSprockets() : Number
  }

  class Bar {
  }

  class Foo extends Bar implements IBaz {
    var sprockets : Number = 4
    function Foo() { /* c'tor */ }
    function getSprockets() : Number {
      return sprockets;
    }
  }

In July of 2000, Microsoft announces JScript.NET

Compile time + Runtime Checking

A brief look at the history of types in JavaScript...

June 2017

June 1997

  
  function foo(i : Number) : Number {
    return i + 1
  }

  var a : Number = 1;

  public class Bar extends Baz { }

  class Foo extends Bar implements IFoo, IFoo2 {
    var sprockets : Number;
    function Foo() {
    }
    function GetSprockets() {
      return sprockets;
    }
  }

September of 2003, ActionScript 2.0 is released with compile-time checking

A brief look at the history of types in JavaScript...

June 2017

June 1997

In 2003 TC-39 progress was all but halted. ES4 was abandoned in favor of ES3.1 > ES5

In 12/2009 ES5 was finally completed

(shipped with IE9 in 2011)

Auth0 "The Real Story Behind ES4" https://auth0.com/blog/the-real-story-behind-es4/

A brief look at the history of types in JavaScript...

June 2017

June 1997


  // ES6
  class Foo extends Bar {
    constructor(sprockets) {
      super(sprockets)
      this.sprockets = sprockets
    }

    doWork() { }

    static sayHello() { }

    get foo() { return true }
    set foo(val) { /* ... */ }
  }

SoundScript

  
  // Stage 2
  class Baz {
    widgetCount = 5
    static name = "FooBar"

    onHandleEvent = () => { /* ... */ }

    #secret = 'shhh'

    @special
    doWork() {
      console.log(this.#secret)
    }
  }

A brief look at the history of types in JavaScript...

June 2017

June 1997

March 2017 WebAssembly reaches cross-browser consensus

A brief look at the history of types in JavaScript...

Additional References

If you want standardized warnings ... we need lots more developer experience to get anywhere near a standard. If you want a static type system -- which means soundness -- then there are big open research problems to solve.

Brendan Eich

Standards, Proposals and the Future

The difference between type annotations as part of the syntax versus the behavior of the engine.

Static type checker for JavaScript


  function square(n) {
    return n * n // Error!
  }

  square("2")

Flow understands JavaScript as it's written today, so that much of the time you don't need type annotations.

3 ways to get your "Flow"

  • Comments
  • Babel
  • flow-remove-types*

*Also available as a plugin for rollup, browserify and webpack

import SomeClass from 'some-module'
import type { IFoo } from 'some-module'

export class MyClass<T> implements IFoo {

  value: T

  constructor(value: T) {
    this.value = value
  }

  get(): T {
    return this.value
  }
}
import SomeClass from 'some-module'

export class MyClass {

  constructor(value) {
    this.value = value
  }

  get() {
    return this.value
  }
}

(Pass the --pretty option)

3 ways to get your "Flow"

// @flow
/*:: import type { IFoo } from './IFoo'*/

export class MyClass/*::<T> implements IFoo*/ {

  /*::value: T */

  constructor(value/*: T*/) {
    this.value = value
  }

  get()/*: T*/ {
    return this.value
  }
}

Using Comments

This means you can use flow without any kind of transpiler/build step.

Let's get started

  • npm init
    This creates your package.json
  • npm install --save-dev flow-bin
    This installs flow
  • Add a "flow" script to your package.json
    This tells npm how to run flow commands
{
  // ...
  "scripts": {
    "flow": "flow"
  }
  // ...
}
  • npm run flow init
    This sets up a basic .flowconfig
  • npm run flow
    This starts the flow background process and checks your code
  • Add // @flow to your code

Flow in your IDE

Flow for ... VS Code?

Flow for ... VS Code?

Install, then click "Reload", then "Reload Window"

Step 1. Install Flow for Visual Studio Code

Flow for ... VS Code?

Step 2. Set your workspace (this project) to use Flow for validation instead of TypeScript for .JS files

Flow for ... VS Code?

Step 2. Set your workspace (this project) to use Flow for validation instead of TypeScript for .JS files

Flow for ... VS Code?

Step 3. Profit

You should now have squigglies, intellisense, etc. provided from Flow.

PS. Some things need saving to update

Flow for ... WebStorm?

WebStorm understands flow annotations out of the box.

Even without flow installed.

To get the best experience, set the JavaScript language to "Flow" and tell WebStorm where the executable is.

File > Settings > Languages & Frameworks > JavaScript

C:\Users\<UserName>\AppData\Roaming\npm\flow.cmd

You can also run "where flow" from Windows.

Didn't find it? npm install -g flow

Flow for ... Visual Studio?

Other ways to work with flow...

Nuclide (built-in)

Atom.io (via flow-ide)

vim (via vim-flow)

emacs, sublime, etc.

Flow at ... runtime?

Check types both at compile and at runtime using babel, exclude the runtime type checks for production.

FlowTyped


  // @flow
  import jQuery from 'jquery'

  jQuery('#id').clicky() // No errors...?

npm install -g flow-typed

flow-typed install


  4: jQuery('#id').clicky()
                   ^^^^^^ property `clicky`. Property not found in
  4: jQuery('#id').clicky()
     ^^^^^^^^^^^^^ JQuery

Ahhh, that's better.

Flowgen

npm install -g flowgen

flowgen myfile.d.ts -o myfile.flow.js

Now you can convert TypeScript definitions.

  • Take a C# model
  • Generate a TypeScript definition
  • Convert it to Flow and add it to [libs]

Flow is not perfect.

  • Flow Typings has a fraction of the libraries of DefinitelyTyped/Typings
     
  • Flowgen doesn't understand all TypeScript definitions
     
  • If you point flow at node_modules it typechecks everything
     
  • TypeScript often performs better/faster than flow, especially with Microsoft technology

Leveraging other languages for type safety

Static Typing - Compile-to-JS

Fable (F# to JS)

JSIL, SharpKit, Bridge.NET (C#/MSIL to JS)

JSweet (Java to JS)

...and many, many more.

(in particular, Fable can use TypeScript definitions for external JavaScript libraries via ts2fable)

Static Typing - Compile-to-WASM

The Mono team has already started work on a C# to WASM compiler.

Mozilla's goal is for Rust to be a first-class language to compile to WASM:

https://hackernoon.com/compiling-rust-to-webassembly-guide-411066a69fde

...and others

Thanks!

Made with Slides.com