Less known parts

for people in hurry

Piotr Lewandowski

interface FoodDelivery {
    orderPizza(ingrediens: any): any;
}
pizzaMaker.orderPizza(
    "ananas"
);

Extend library

pizzaMaker.orderPizza("ananas");
declare interface FoodDelivery {
    orderPizza(ingrediens: string[]): number;
    orderPizza(ingrediens: string): number;
}

declare var pizzaMaker: FoodDelivery;

Describes JavaScript

Static typing

State of the ar

Static != Strong

Java / C# static and strong typing
TypeScript static and weak typing
JavaScript dynamic and weak typing
class JavaGroup {
    id : number = 1;
    hour : string = "13:30";
}

class FrontendGroup {
    id: number = 2;
    hour: string = "14:30"
}

let skm: JavaGroup = 
    new JavaGroup();

Structural typing

skm = new FrontendGroup();
let isJava = 
    skm instanceof JavaGroup;
skm = {
    id: 3,
    name: ".Net",
    hour: "15:30?"
};
let x = (a: number) => 0;
let y = (b: number, s: string) => 0;

x(1);

y(1, "2");

Structural typing

y = x; // OK
x = y; // Error
class RequestBuilder {
    get(): RequestBuilder {
        // set some params;
        
        return this;
    }
}

class CrudRequest 
            extends RequestBuilder {

    post() : CrudRequest {
        return this;
    }

    delete() : CrudRequest {
        return this;
    }
}
let request = new CrudRequest()
    .post()
    .get()
    .delete();

    // ??? No method found
    // on type 'RequestBuilder'

Polymorphic this

livecode

class RequestBuilder {
    get(): this {
        // set some params;
        
        return this;
    }
}

class CrudRequest 
            extends RequestBuilder {

    post() : this {
        return this;
    }

    delete() : this {
        return this;
    }
}
let request = new CrudRequest()
    .post()
    .get()
    .delete();

    // :)

Polymorphic this

livecode

keyof

interface Point {
    x: number;
    y: number;
}

type Dimensions = keyof Point; // "x" | "y"

let dimension : Dimensions = "z" // Error;
interface PizzaIngredients {
    peperoni: boolean;
    doubleCheese: boolean;
    sauce: "ketchup" | "garlic";
}

const pizza: PizzaIngredients = {
    peperoni: true,
    doubleCheese: true,
    sauce: "ketchup"
};

const value = pizza['peperoni'];
var pizza = {
    peperoni: true,
    doubleCheese: true,
    sauce: "ketchup"
};

var value = pizza['peperoni'];

Problem

Element implicitly has an 'any' type 
because type 'PizzaIngredients' 
has no index signature.
interface PizzaIngredients {
    peperoni: boolean;
    doubleCheese: boolean;
    sauce: "ketchup" | "garlic";
}

const pizza: PizzaIngredients = {
    peperoni: true,
    doubleCheese: true,
    sauce: "ketchup"
};
let key: string = 'peperoni';
let value: string = (pizza as any)[key];
interface PizzaIngredients {
    peperoni: boolean;
    doubleCheese: boolean;
    [key: string]: boolean;
}

let key: string = 'peperoni';
let value: boolean = pizza[key];
let key: keyof PizzaIngredients = 'peperoni';
let value: boolean = pizza[key];
interface Configuration {
  baseUrl: string;
  port: number;
}
type ConfigurationOption = keyof Configuration; // 'baseUrl' | 'port'

Mapped types

type ConfigurationLastUpdated = { 
  [O in ConfigurationOption]: Date 
};
const updated: ConfigurationLastUpdated = {
  baseUrl: new Date(),
  port: new Date()
};

type Color = 'red' | 'blue' | 'green';


type ColorToRgb = {
    [C in Color]? : string;
};

Mapped types


const rgbMap: ColorToRgb = {
  red: '#ff0000'
};

Generic types

function httpGet(): Promise<string> {
    return Promise.resolve("ok");
}

httpGet()
    .then(data => data.toUpperCase());
interface PromiseConstructor {
  // ...

  resolve<T>(value: T | PromiseLike<T>): Promise<T>;
}
[0, 1, "2"]
interface PromiseConstructor {
  // ...

  all<T1, T2, T3>(values: [T1, T2, T3]): Promise<[T1, T2, T3]>;
}


interface Point {
    x : integer;
    y : integer;
}

type PartialPoint = Partial<Point>;

// =>

interface PartialPoint {
    x? : integer;
    y? : integer;
}
type PartialPoint = {
    [P in keyof Point] ?: Point[P];
};

Generic + mapped

type PartialPoint = {
    [P in "x" | "y"] ?: Point[P];
};
type PartialPoint = {
    x? : Point["x"];
    y? : Point["y"];
};
type PartialPoint = {
    x? : number;
    y? : number;
};

<type assertion>

not casting

let mouseEvent = <MouseEvent> event;
let mouseEvent = event as MouseEvent;

Double casting

function handler (event: Event) {
    let mouseEvent = event as MouseEvent;
}
function handler(event: Event) {
    let element = event as HTMLElement; // Error
}
function handler(event: Event) {
    let element = event as any as HTMLElement; // OK
}

type guards

next time maybe :)

function counter(state = 0, action: Action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1
  case 'DECREMENT':
    return state - 1
  default:
    return state
  }
}

Redux

Further reading

TypeScript less known part

By Piotr Lewandowski

TypeScript less known part

We talk about typing system, which is more advanced than Java or C#.

  • 322