1. Back to the Future
    1. Dynamic typing in JS
    2. How JS analyze and compile code
  2. flow - static code analyze
    1. How it works and whats its' goal
    2. Flow graphs how they are usefull
    3. Daily work
      1. Primitive types
      2. Maybe
      3. Object types
        1. Sealed
        2. Unseal
        3. Exact types
      4. Classes
        1. Nominal and structural typing
      5. Special types
        1. Function
        2. Mixed
        3. Any
  3. Tools
  4. Issues
  5. Q&A

Scop and compilation

Dynamic typing in JS

var foo = "test";
foo = 32;
foo = true;

var bar = foo + 42;

var foobar = (a) => a + "2";

foobar(20);

foobar("test"); 

foobar = (b) => b;

foobar(bar);

flow

to be

precise and fast

and

sound and complete as possible

OK, so how it works?

var foo = "test";

foo.lenght;

How those graphs may be useful?

Daily work

Primitive types

  1. Boolean
  2. Null
  3. Undefined
  4. Number
  5. String
  6. Symbol (not supported by flow)

Maybe

flow defines optional maybe type. With this type you can specify if the value will have user type, null or undefined.

function<T> foo(bar: ?T)

function bar(num: ?number){
    return num;
}


bar(5);
bar(null);
bar(undefined);

function bar(num: ?number){
    if(num){
        return num * 2;
    }
}

Object

flow defines object type as similar to JS as possible with some extra features like:

  • sealed objects
  • unsealed objects
  • exact objects
var obj: {foo: string, bar: number} = {foo: "test", bar: 5};
var optional: {foo: string, bar?: number} = {foo: "test"}; 
var sealed: {foo: string, bar: number} = {foo: "test", bar: 5}; var a: num = sealed.lack;
var unsealed: {}, var unsealed.foo = "test", unsealed.bar = 5;
var exact = (obj: {|foo:number|}) => {...}

exact({foo:5, bar: "test"});
exact({foo: 5});

Class

flow defines class type the same as in JS. The biggest difference is that flow treats classes as nominal type.

class FooClass{
    property: number;
	
    constructor(property:number){}
    
    foo(){
        this.property;
    }
}

var bar: FooClass = new FooClass(5);

class GenericClass<A, B, C>{
    propertyA: A;
    propertyB: B;

    constructor(propertyA: A, propertyB: B){}

    foo(): C {
 	return ...;
    }
}

var baz: GenericClass<number, string, boolean> 
  = new GenericClass(5, "test");

Class

You can define properties in class as writeOnly and readOnly using property variance.

class FooClass{
    +bar: number; //read only
    -foo: string; //write only
	
    constructor(bar: number, foo: string){}
}

var baz: FooClass = new FooClass(5, "test");

baz.bar = 10;

baz.foo;

Nominal and structural typing

type FuncType = (a:string) => void;
function func(a:string) { }
var newFunc:FuncType = func; // it's ok!

type ObjType = {foo: string};
var object = {foo: "test"};
var o:ObjType = object; // it's ok!

class ClassA { foo: string; }
class ClassB { foo: string; }
var c:ClassA = new ClassB(); // error!

Due to its object-oriented and functional nature JavaScript, flow is both nominal and structural typed. 

Structural Nominal
objects classes
functions

Special types

In flow you can use several "special" types that can handle some of edge cases:

  • mixed
  • Function
  • any
// MIXED
function foo(x:mixed){
    return "" + x;
}

foo(3);
foo("test");
foo(null);

// FUNCTION
function method(func: Function) {
  func(1, 2);     // Works.
  func("1", "2"); // Works.
  func({}, []);   // Works.
}

method((a:number, b:number) => {});

// ANY
function bar(a:any, b:any): any{
    var foo = a;
    
    typeof foo == "number";
    typeof foo == "string"
}

bar(3, "test").length

Tools

Advantages

  • null safe at runtime
  • configured for max security
  • simple to introduce to existing projects
  • fast

Issues

  • error messages
  • poor IDE support
  • poor github response time
  • fails with ES6 spread operator 

q & a

flow

By Krzysztof Folwarczny