Oliver Zeigermann / @DJCordhose
http://djcordhose.github.io/react-intro-live-coding/2016_jsunconf.html
let obj: string;
obj = 'yo';
// Error: number: This type is incompatible with string
obj = 10;
function sayIt(what: string) {
return `Saying: ${what}`;
}
const said: string = sayIt(obj);
class Sayer {
what: string;
constructor(what: string) {
this.what = what;
}
sayIt(): string {
return `Saying: ${this.what}`;
}
}
const element = <HelloMessage greeting="Hello"/>;
ReactDOM.render(element, mountNode);
// ERROR: Must be a ReactElement
const element = 'just a string'; // type is interred as string
ReactDOM.render(element, mountNode);
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
// just to make this different from cat
goodBoyFactor: number;
}
class Cat extends Animal {
purrFactor: number;
}
Types can be parameterized by others
Most common with collection types
let cats: Array<Cat> = []; // can only contain cats
let animals: Array<Animal> = []; // can only contain animals
// nope, no cat
cats.push(10);
// nope, no cat
cats.push(new Animal('Fido'));
// cool, is a cat
cats.push(new Cat('Purry'));
// cool, cat is a sub type of animal
animals.push(new Cat('Purry'));
type Props = {
// ERROR: trying to assign this boolean to state
// greeting: boolean
greeting: string
};
type State = {
greeting: string;
};
class HelloMessage extends React.Component<any, Props, State> {
constructor(props: Props) {
super(props);
this.state = {greeting: this.props.greeting};
}
}
function foo(num: number) {
if (num > 10) {
return 'cool';
}
}
// error: call of method `toString`.
// Method cannot be called on possibly null value
console.log(foo(100).toString());
Flow does catch this
But why?
The inferred type is something else
// error: return undefined. This type is incompatible with string
function foo(num: number): string {
if (num > 10) {
return 'cool';
}
}
// nullable type: the one inferred
function foo(num: number): ?string {
if (num > 10) {
return 'cool';
}
}
// to fix this, we need to check the result
const fooed: ?string = foo(100);
if (fooed) {
fooed.toString();
}
Types are non-nullable by default in Flow
Nullable types in Flow also possible
type Action<ActionType, PayloadType> = {
type: ActionType;
payload: PayloadType;
}
// Action is a generic type
type GreetingAction =
Action<'UPDATE_GREETING' | 'RESET_GREETING', ?string>;
function updateGreeting(greeting: string): GreetingAction {
return {
// must be UPDATE_GREETING' or 'RESET_GREETING
type: 'UPDATE_GREETING',
// must be a string or null/undefined
payload: greeting
};
}
function resetGreeting(): GreetingAction {
return {
type: 'RESET_GREETING',
// payload may be null or undefined
payload: null
};
}
// ERROR: this for sure is string
// function greetingReducer(state = 'Hello', action): number {
function greetingReducer(state: string = 'Hello',
action: GreetingAction): ?string {
// flow will likely check that all cases are matched in the future
// https://github.com/facebook/flow/issues/1473
switch (action.type) {
case 'UPDATE_GREETING':
return action.payload;
case 'RESET_GREETING':
return '';
default:
return state;
}
}