Generics: the ability to abstract types

Generic Function

  1. function identity<T>(value: T): T {
  2. return value;
  3. }
  4. // Automatic structure checks
  5. function get<T, K extends keyof T>(p: T, key: K): any {
  6. return p[key]
  7. }

Generic Interfaces

interface Identities<V, W> {
   id1: V,
   id2: W
}

function identities<T, U> (arg1: T, arg2: U): Identities<T, U> {
   console.log(arg1 + ": " + typeof (arg1));
   console.log(arg2 + ": " + typeof (arg2));
   let identities: Identities<T, U> = {
    id1: arg1,
    id2: arg2
  };
  return identities;
}

Generic classes

abstract class Animal {
    handle() { throw new Error("Not implemented") }
}

class Horse extends Animal{
    color: string
    handle() {
        console.log("Riding the horse...")
    }
}

class Dog extends Animal{
    name: string 
    handle() {
        console.log("Feeding the dog...")
    }
}

class Handler<T extends Animal> {
    animal: T

    constructor(animal: T) {
        this.animal = animal
    }

    handle() {
        this.animal.handle()
    }
}

class DogHandler extends Handler<Dog> {}
class HorseHandler extends Handler<Horse> {}

Variadic Tuples

type MyTuple<T extends unknown[]> = [string, string, ...T, number]

let myList:MyTuple<[boolean, number]> = ["Fernando", "Doglio", true, 3, 37]
let myList:MyTuple<[number, number, number]> = ["Fernando", "Doglio", 1,2,3,4]

usage

Typing Dynamic Objects and Subsets with Generics

type Pick<T> = { [K in keyof T]: T[K] };
function pick<T> (obj: T, keys: (keyof T)[]): Pick<T> {
    throw "not yet implemented"
}

type Pick<T, U extends keyof T> = { [K in U]: T[K] };
function pick<T, U extends keyof T> (obj: T, keys: U[]): Pick<T, U> {
    throw "not yet implemented"
}

keyof syntax

// some article type
type Article = {
   title: string,
   id: number,
   ...
}
// some key of article
type Key = keyof Article;
// some array of keys of article
type KeyArray = (keyof Article)[];

Typing the return type based on keys provided

const articleTitle = pick(article, ["title"]);
type resolved = typeof articleTitle;

Typescript Generics Explained