100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
TypeScript

Generic Functions in TypeScript

Learn how to write and call generic functions in TypeScript, including type inference, explicit type arguments, and multi-parameter generics.

GenericsIntermediate9 min readJul 8, 2026
Analogies

1. Introduction

A generic function is a function whose parameter and/or return types are expressed using one or more type parameters instead of concrete types. This lets a single function definition safely handle many different input types, while the compiler still checks that everything lines up correctly for each call — something plain JavaScript functions or any-typed functions cannot do.

🏏

Cricket analogy: A generic selectOpener<T>(players: T[]): T function can pick from a lineup of Batter objects or Allrounder objects using one definition, while the compiler still checks each call — something an any-typed selector for Rohit Sharma's team could never guarantee.

2. Syntax

typescript
// Single type parameter
function firstElement<T>(items: T[]): T {
  return items[0];
}

// Multiple type parameters
function pair<T, U>(first: T, second: U): [T, U] {
  return [first, second];
}

// Generic arrow function
const wrapInArray = <T,>(value: T): T[] => [value];

// Generic function type (for variables/parameters)
let mapper: <T, U>(value: T, fn: (v: T) => U) => U;

3. Explanation

Generic functions let you write reusable code that works over a variety of types while preserving type information — the return type of firstElement<T>(items: T[]): T is always exactly the element type of whatever array you pass in, never a loosely typed any. This is what distinguishes it from a version typed as (items: any[]) => any, which would lose that guarantee completely.

🏏

Cricket analogy: firstElement<T>(lineup: T[]): T returns exactly the batter type you passed in, so firstElement(kohliLineup) returns a Batter, never a loosely typed any — unlike (items: any[]) => any, which loses that guarantee entirely.

TypeScript infers type parameters from the arguments at the call site whenever possible, so most of the time you never need to write the angle brackets yourself. You only need explicit type arguments (e.g. pair<number, string>(1, "a")) when the compiler cannot infer a type unambiguously, such as when a generic function is called with no arguments that reference the type parameter.

🏏

Cricket analogy: Calling matchScore(180, "win") lets TypeScript infer the generic types from the arguments automatically, but a function called with no arguments referencing T, like starting a fresh tally<number, string>() for a new innings, needs the type arguments written explicitly.

Multi-parameter generic functions, like pair<T, U>, follow the T, K, V, U naming convention — T and U are used together when two independent, unrelated types are involved. Generic functions are also frequently combined with keyof for type-safe property access: function getProp<T, K extends keyof T>(obj: T, key: K): T[K] guarantees that key is actually a valid property name of obj, and that the return type matches that property's type exactly.

🏏

Cricket analogy: function pair<T, U>(name: T, average: U) pairs Kohli's name (T) with his batting average (U) as two unrelated types, and combining that with keyof in getProp<T, K extends keyof T>(player, key) guarantees the requested stat field truly exists.

Gotcha: in a .tsx file, <T,> (with a trailing comma) or <T extends unknown> must be used instead of plain <T> for generic arrow functions, because the parser would otherwise try to interpret <T> as the start of a JSX element.

4. Example

typescript
function firstElement<T>(items: T[]): T {
  return items[0];
}

function pair<T, U>(first: T, second: U): [T, U] {
  return [first, second];
}

function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const numbers = [10, 20, 30];
const names = ["Ada", "Grace", "Linus"];

console.log(firstElement(numbers));  // T inferred as number
console.log(firstElement(names));    // T inferred as string

const combo = pair("score", 95); // T=string, U=number
console.log(combo);

const user = { id: 1, name: "Ada Lovelace" };
console.log(getProp(user, "name")); // K constrained to 'id' | 'name'
// getProp(user, "email"); // compile error: 'email' is not a key of user

5. Output

text
10
Ada
[ 'score', 95 ]
Ada Lovelace

6. Key Takeaways

Practice what you learned

Was this page helpful?

Topics covered

#TypeScript#TypeScriptProgrammingStudyNotes#Programming#GenericFunctionsInTypeScript#Generic#Functions#Syntax#Explanation#StudyNotes#SkillVeris