TypeScript Generics

Write one function that keeps the type of whatever it receives.

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

const n = first([10, 20, 30]);
const s = first(["a", "b"]);
const none = first<number>([]);
console.log(n, s, none);
Output
10 a undefined

Explanation

A generic function takes a type parameter, written <T>, so it can work with many types while still being checked. first<T> returns the first element of a T[] and has the return type T | undefined.

TypeScript usually infers T from the argument, so first([10, 20, 30]) is a number | undefined. When there is nothing to infer from, such as an empty array, you can pass the type yourself with first<number>([]).

Explore the dry run
Guided walkthroughReady
1function first<T>(items: T[]): T | undefined {
2 return items[0];
3}
4
5const n = first([10, 20, 30]);
6const s = first(["a", "b"]);
7const none = first<number>([]);
8console.log(n, s, none);

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
T is a placeholder filled in at each call.—
—
T is inferred as number, so n is 10.n = 10
—
T is inferred as string, so s is "a".s = "a"
—
An empty array has no first element, so the result is undefined.none = undefined
—
console.log separates its arguments with a space.none = undefined
10 a undefined

Cost and common mistakes

O(1) time and space per call.

  • Indexing an empty array returns undefined at runtime, which is why the return type includes undefined.
  • Generics are erased at compile time; you cannot test T at runtime.

Try it yourself

Write last<T>(items: T[]) that returns the final element.

Reveal answer and reasoning

return items[items.length - 1]; the return type is again T | undefined.

Further reading