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 | undefinedthat returnsarr[0], - create
const nums: number[] = [7, 14, 21];andconst words: string[] = ["alpha", "beta"];, - print
"first number = " + first(nums)and"first word = " + first(words)withconsole.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.
Free plan: 30 tutor messages. PRO is unlimited.
