Generic Type Parameters Make Your Components Reusable Over A Variety Of Types

TopicSource
๐Ÿฆ’ TypeScriptTypeScript: Documentation - Generics

Identity Function: the Hello World of Generics

If you want type safety for a function, where you don't know the specific type that will be used, you can use generics to define the type. A generic is written in <> and works like a placeholder for the type.

const identity = function <TValue> (value: TValue): TValue {
  return value;
};

let x = 23;
const result = identity(x);

export {};

Generics in Classes and Interfaces

You can also use generics in classes and interfaces. To accomplish this, you have to define the class/interface itself with a generic.

interface Stack<TValue> { // you define the generic here
  isEmpty: () => boolean;
  push: (value: TValue) => void;
  top: () => TValue;
  pop: () => TValue;
}

class InMemoryStack<TValue> implements Stack<TValue> { //you have to pass the generic through
  values: TValue[];

  constructor () {
    this.values = [];
  }

  isEmpty (): boolean {
    return this.values.length === 0;
  }

  push (value: TValue): void {
    this.values.unshift(value);
  }

  top (): TValue {
    return this.values[0];
  }

  pop (): TValue {
    const topMostValue = this.values.shift()

    if (topMostValue === undefined) {
      throw new Error('Invalid operation.');
    }

    return topMostValue;
  }
}

const stack = new InMemoryStack<number>(); // here you can define a concrete instance wtih a specific type to create a stack of numbers

stack.push(42);
stack.push(23);
stack.pop();

Generics that Fulfil a Certain Condition

Imagine you have a function using a generic, but you want to call a specific property or function, that the generic has to provide. In this case, you can extend the generic with an interface. In this case, the generic has to provide a name, so we add a HasName interface that the generic implements.

interface HasName {
  name: string;
}

const getName = function <TValue extends HasName> (value: TValue): TValue {
  console.log(value.name);
  return value;
};

const person1 = {
  name: 'Dana K. Scully',
  department: 'X-Files'
};

const person2 = {
  nickName: 'The smoker',
  department: 'CIA'
};

const scully = getName(person1);

export {};


  1. Interfaces in TypeScript
  2. Creating classes that implement an interface in TypeScript