Reuse a type

INPUT · Slides

A function with a type parameter

01 / 05

Writing the same function for every type is a pain

Say you want a function that takes an array and returns the first item. You want it for arrays of strings and for arrays of numbers.

As things stand, you end up writing the same function over again, once per type.

function firstS(list: string[]): string {  return list[0];}function firstN(list: number[]): number {  return list[0];}console.log(firstS(["a", "b"]));console.log(firstN([3, 5]));

Result

a
3

02 / 05

Go any[] and the type disappears

So should you just make it any[]? Better not. Declare "anything will do" and you also lose track of what comes back.

The code below gets not a single type error. But what is in s is the number. Look at length thinking it is a string and the answer is undefined.

function first(list: any[]): any {  return list[0];}const s: string = first([10, 20]);console.log(s.length);

Result

undefined

03 / 05

Write a type parameter <T>

Write <T> after the function name and it means "the type of the contents is not decided here. Whoever calls it decides."

After that you just use T like any other type name.

  • it takes a T[]
  • it returns a T
function first<T>(list: T[]): T {  return list[0];}console.log(first(["a", "b"]));console.log(first([3, 5]));

Result

a
3

04 / 05

The type you hand over carries through to the return

T gets swapped for the real type when it is called. Hand it an array of strings and what comes back is a string too.

So if you try to put what came back into a number variable, it stops you. That is where any waved you straight through.

function first<T>(list: T[]): T {  return list[0];}const n: number = first(["a", "b"]);

Result

Type error: Type 'string' is not assignable to type 'number'.

05 / 05

T is just a name

T has no fixed meaning. It borrows the first letter of "type", and any other name works. But most people write T, so going along with it reads better.

What you take need not be an array either. A function that just gives a value straight back can use it too. Now write some yourself.

function asIs<T>(value: T): T {  return value;}console.log(asIs("candy"));console.log(asIs(12));console.log(asIs(true));

Result

candy
12
true