Start learning free

LESSON 53 OF 675 · FUNCTIONS I

Generics: one function, any array

Lesson

You already know how to write a function that works on a number[]. Say you want the first element of an array:

function firstNumber(arr: number[]): number | undefined {
    return arr[0];
}

It works — but only for numbers. The moment you need the same thing for strings, you have a problem.


The trap:

Hand your number-only function a string[]:

const words: string[] = ["alpha", "beta"];
firstNumber(words);

...and the compiler stops you cold:

error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number[]'.
  Type 'string' is not assignable to type 'number'.

Read it bottom-up: a string can't live where a number is required, so the whole array is rejected. Your two escape routes both hurt: copy-pasting a firstString twin duplicates code forever, and switching the parameter to any[] compiles — but the result becomes any and TypeScript stops checking anything you do with it.


The fix: a type placeholder.

Write <T> after the function name to declare a generic type parameter — a placeholder that gets filled in fresh at every call:

function first<T>(arr: T[]): T | undefined {
    return arr[0];
}

first([7, 14, 21]);        // T becomes number — returns number | undefined
first(["alpha", "beta"]);  // T becomes string — returns string | undefined

You never write the type argument yourself — TypeScript infers T from whatever array you pass. One function, full type safety for every element type.

And why T | undefined instead of just T? Because arr[0] on an empty array evaluates to undefined — the signature is honest about that possibility instead of promising a value it might not have.


Assignment
Follow the Coding Tutorial and build it yourself:

  • define function first<T>(arr: T[]): T | undefined that returns arr[0],
  • create const nums: number[] = [7, 14, 21]; and const words: string[] = ["alpha", "beta"];,
  • print "first number = " + first(nums) and "first word = " + first(words) with console.log.

The exact expected output is:

first number = 7
first word = alpha

Hint
You could call first<number>(nums) with an explicit type argument, but you almost never need to — inference fills in T from the argument.


STEP 1 OF 6
    Ctrl + Enter to check