Curriculum
Course: TypeScript
Login
Text lesson

TS Basic Generics

Generics enable the creation of ‘type variables’ that can be used in classes, functions, and type aliases without explicitly defining the types they use.

Generics facilitate writing reusable code.

Functions

Generics with functions allow for more generalized methods that accurately represent the types used and returned.

Example

function createPair<S, T>(v1: S, v2: T): [S, T] {
  return [v1, v2];
}
console.log(createPair<string, number>(‘hello’42)); // [‘hello’, 42]

TypeScript can infer the type of the generic parameter based on the function parameters.

Classes

Generics can be used to create generalized classes, such as Map.

Example

class NamedValue<T> {
  private _value: T | undefined;

  constructor(private name: string) {}

  public setValue(value: T) {
    this._value = value;
  }

  public getValue(): T | undefined {
    return this._value;
  }

  public toString(): string {
    return `${this.name}: ${this._value}`;
  }
}

let value = new NamedValue<number>(‘myNumber’);
value.setValue(10);
console.log(value.toString()); // myNumber: 10

TypeScript can also infer the type of the generic parameter when it is used in a constructor parameter.

Type Aliases

Generics in type aliases enable the creation of more reusable types.

Example

type Wrapped<T> = { value: T };

const wrappedValue: Wrapped<number> = { value: 10 };

This also applies to interfaces, using the following syntax: interface Wrapped<T> {.

 

Default Value

Generics can be assigned default values, which are used if no other value is specified or inferred.

Example

class NamedValue<T = string> {
  private _value: T | undefined;

  constructor(private name: string) {}

  public setValue(value: T) {
    this._value = value;
  }

  public getValue(): T | undefined {
    return this._value;
  }

  public toString(): string {
    return `${this.name}: ${this._value}`;
  }
}

let value = new NamedValue(‘myNumber’);
value.setValue(‘myValue’);
console.log(value.toString()); // myNumber: myValue

Extends

Constraints can be added to generics to limit what types are allowed. These constraints enable reliance on a more specific type when using the generic type.

Example

function createLoggedPair<S extends string | number, T extends string | number>(v1: S, v2: T): [S, T] {
  console.log(`creating pair: v1=’${v1}’, v2=’${v2}’`);
  return [v1, v2];
}

This can be combined with a default value for the generic type.