genkio / blog

Stay hungry stay foolish
https://slashbit.github.io/blog/
0 stars 1 forks source link

TypeScript bits and pieces #188

Open genkio opened 5 years ago

genkio commented 5 years ago

Simple class example

class User {
  static readonly minimumNameLength: number = 4;

  constructor(private _name: string, private readonly email: string) {
    User.assertValidName(_name);
  }

  static assertValidName(name) {
    const nameIsValid = name.length >= User.minimumNameLength;
    if (!nameIsValid) {
      throw Error("The given name is not valid");
    }
  }

  get name(): string {
    return this._name;
  }

  set name(newName: string) {
    User.assertValidName(newName);
    this._name = newName;
  }

  speak() {
    console.log(`I am ${this.name}!!!`);
  }
}

Constructor shorthand

class Foo {
    x: number;
    constructor(x:number) {
        this.x = x;
    }
}
// equivalent
class Foo {
    constructor(public x:number) {
    }
}
// one step further
class ParamPropContact {
    constructor(
        public name: string,
        public email: string = "no email") {}
    }
}

image

Property initializer (ES7)

class Foo {
    members = [];  // Initialize directly
    add(x) {
        this.members.push(x);
    }
}

Understanding generics

image

Adding constraints to type parameters

function arrayToDict<T extends { id: string }>(array: T[]): { [k: string]: T} {
    const out: { [k: string]: T } = {};
    array.forEach(val => {
        // extends { id: string } is telling ts T has a key as id
        out[val.id] = val;
    });
    return out;
}

// improve 
function arrayToDict(array: ({ id: string })[]): { [k: string]: { id: string }} {
    const out: { [k: string]: T } = {};
    array.forEach(val => {
        // extends { id: string } is telling ts T has a key as id
        out[val.id] = val;
    });
    return out;
}

Matching key to value using extends keyof

interface CommunicationMethods {
    email: HasEmail;
    phone: HasPhone;
    fax: { fax: number };
}

function contact<K extends keyof CommunicationMethods>(
    method: K,
    contact: CommunicationMethods[K]
) {
    //....
}
contact("email", { // only HasEmail appliance value is allowed })

Creating new types with keys or values of another type

type AllCommunicationMethods = keyof CommunicationMethods;
type AllCommunicationValues = CommunicationMethods[keyof CommunicationMethods];

Using typeof to create your own type base on other's type

type ResolveType = typeof Promise.resolve;

Use readonly to prevent errors from mutating objects

image

Prefer function expressions over function declarations for type reusability

image

Prefer unknown over any to get better type safety

image

Lean into JSDoc or TSDoc style comments for better development experience

image