#typescript #generics #advanced

Day 15: Generics - Making Reusable Code

The “Variable” for Types

Welcome to Day 15! Today we tackle one of the most important concepts in TypeScript: Generics.

Imagine you want a function that returns whatever you pass in.

function identity(arg: any): any {
  return arg;
}

This works, but we lose type safety. If we pass a number, the return type is any, not number.

Introducing Type Variables

We use <T> (or any letter) to capture the type provided by the user.

function identity<T>(arg: T): T {
  return arg;
}

Now usage:

let output = identity<string>("myString"); 
// type of output is 'string'

let output2 = identity(100); 
// type of output2 is 'number' (Inferred!)

Generic Interfaces

You can make interfaces generic too.

interface Box<T> {
  contents: T;
}

let stringBox: Box<string> = { contents: "Hello" };
let numberBox: Box<number> = { contents: 42 };

Generic Classes

class StorageContainer<T> {
  private data: T[] = [];

  addItem(item: T) {
    this.data.push(item);
  }

  getItem(index: number): T {
    return this.data[index];
  }
}

const names = new StorageContainer<string>();
names.addItem("Jack");

Generics allow us to write code that is flexible and type-safe.

Challenge for Today

  1. Create a generic function wrapInArray<T>(item: T): T[].
  2. It should take an item and return an array containing that item.
  3. Test it with a string and a number.
  4. Verify the return type is string[] and number[] respectively.

See you on Day 16 where we Constrain our generics!