On Github kpuputti / flow-and-static-types
and static types for JavaScript
Frontend Weeklies, 2014-12-05
Maintaining large JavaScript codebases takes effort
some options
import 'dart:io'; import 'dart:async'; void printDailyNewsDigest() { File file = new File("dailyNewsDigest.txt"); Future future = file.readAsString(); future.then((content) { print(content); }); }
@Component({selector: 'foo'}) class MyComponent { @Inject() constructor(server:Server) {} }
interface Person { firstname: string; lastname: string; } function greeter(person : Person) { return "Hello, " + person.firstname + " " + person.lastname; } var user = {firstname: "Jane", lastname: "User"}; document.body.innerHTML = greeter(user);
declare module Rx { export interface Observable<T> { (dueTime: Date, scheduler?: IScheduler): Observable<T>; delay(dueTime: number, scheduler?: IScheduler): Observable<T>; throttle(dueTime: number, scheduler?: IScheduler): Observable<T>; timeInterval(scheduler?: IScheduler): Observable<TimeInterval<T>>; timestamp(scheduler?: IScheduler): Observable<Timestamp<T>>; sample(interval: number, scheduler?: IScheduler): Observable<T>; sample<TSample>(sampler: Observable<TSample>, scheduler?: IScheduler): Observable<T>; timeout(dueTime: Date, other?: Observable<T>, scheduler?: IScheduler): Observable<T>; timeout(dueTime: number, other?: Observable<T>, scheduler?: IScheduler): Observable<T>; } }
/* @flow */ function foo(x) { return x * 10; } foo('Hello, world!');
$> cd flow/examples/01_HelloWorld $> flow check
01_HelloWorld/hello.js:7:5,17: string This type is incompatible with 01_HelloWorld/hello.js:4:10,13: number
function id(x) { return x; }
function id<T>(x: T): T { return x; }
See Parametricity by @dibblego for an explanation why generic functions are awesome
/* @flow */ var o = null; print(o.x);
file.js:3:7,9: property x Property cannot be accessed on possibly null value file.js:2:9,12: null
/* @flow */ function length(x) { return x.length; } var total = length('Hello') + length(null);
03_Null/nulls.js:4:10,17: property length Property cannot be accessed on possibly null value 03_Null/nulls.js:7:38,41: null
/* @flow */ function length(x) { if (x !== null) { return x.length; } else { return 0; } } var total = length('Hello') + length(null);
declare class Promise { constructor(callback); then(onFulfill, onReject); catch(onReject); static cast(object); static resolve(object); static reject(error); static all(promises); static race(promises); }
declare class Promise<R> { constructor(callback): void; // void instead of Promise<R> in Flow core? then<U>(onFulfill, onReject): Promise<U>; }
declare class Promise<R> { constructor(callback: (resolve: (result: R) => void, reject: (error: any) => void) => void): void; // why any instead of Error in Flow core? then<U>(onFulfill, onReject): Promise<U>; }
declare class Promise<R> { constructor(callback: (resolve: (result: R) => void, reject: (error: any) => void) => void): void; then<U>(onFulfill?: (value: R) => Promise<U> | U, onReject?: (error: any) => Promise<U> | U): Promise<U>; }
Note map vs. monadic bind (flatMap) in the then handler!
declare class Promise<R> { constructor(callback: (resolve: (result: R) => void, reject: (error: any) => void) => void): void; then<U>(onFulfill?: (value: R) => Promise<U> | U, onReject?: (error: any) => Promise<U> | U): Promise<U>; catch<U>(onReject?: (error: any) => U): Promise<U>; static cast<T>(object?: T): Promise<T>; static resolve<T>(object?: T): Promise<T>; static reject(error?: any): Promise<any>; static all<T>(promises: Array<Promise<T>>): Promise<Array<T>>; static race<T>(promises: Array<Promise<T>>): Promise<T>; }