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>;
}
}
"However, in practice, we notice that developers often—for 50% of all variables—use the `any` type, thus making TypeScript dynamic and weak"
/* @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>;
}