Types in JS
// Should this fail type-check
function foo(): string { // returns a string type
let arr = [];
return arr[0];
}
Types in JS
Developer ergonomics
Types in JS
let a:string = "a string"
a = null; // <- No type-fail in Typescript
// <- Fails with Flow
Types in JS
Onboarding experience
Types in JS
// Typescript here.
// Flow has similar behaviour
class A{
x: string
}
interface B {
x: string;
}
type C = { x: string };
let a = new A();
let b: B;
let c: C;
b = a; // works
c = a; // works
same shape => same type
Types in JS
Types in JS
Javascript too has classes now, so classes are nominally typed in Flow
// only in Flow
class E {
x: string;
}
class F {
x: string;
}
let e1 = new E();
let f1:F = e1; // <-- Fail
Types in JS
Flow goes a step further
// only in Flow
type A = { x: number }
let a:A = { x: 123, y: 'abc' } // <-- Okay with Flow
Types in JS
Flow goes a step further -
It allows wider values to be assigned to an object
// only in Flow
type A = { x: number, y: number }
let a:A = { x: 123, y: 456, z: 'abc' } // <-- Okay with Flow
let a2:A = { x: 123 } // Not okay
In fact, it allows an value of a subtype to be assigned.
Flow goes a step further -
It allows wider values to be assigned to an object
Types in JS
Structural sub-typing / Type widening
Allows an value of a subtype to be assigned.
Inherited classes are well known as subtypes.
Wider objects are actually sub-types of an object
// Flow
class A { }
class B extends A { }
let a1:A = new B(); // <- Okay
// Same in Typescript too
Types in JS
But this is not without problems.
Type-widening and union types don't play nice together.
// Flow
type A = { x: number }
type B = { y: number }
type C = A | B;
let c:C = { x: 1, y: 1 } // Okay
let d = c.x // Error: x is missing in B
let e = c.y // Error: y is missing in A
type A1 = {| x: number |}
type A2 = {| y: number |}
type C = A | B
let c:C = { x: 1, y: 2 } // Error right here
Fixed using the exact object type
Types in JS
Types in JS
Contravariance
Type-widening and union types don't play nice together.
Fixed using the exact object type
Types in JS
let a: string = "a string"
a = null; // <- No type-fail in Typescript
function foo(x):string {
return undefined // <- No error. Not cool !
}
Typescript considers null a subtype of all types.
In other words, null/undefined can be assigned to a variable of any type
Thankfully,
Types in JS
let a: string = "a string"
a = null; // <- No type-fail in Typescript
function foo(x):string {
return undefined // <- No error. Not cool !
}
The rationale -
Ease of use.
Converting existing code bases gradually is much easier with this.