Question
In TypeScript, regular functions can use generics like this:
function identity<T>(arg: T): T {
return arg;
}
What is the correct syntax for writing an arrow function with generics that behaves the same way?
Short Answer
By the end of this page, you will understand how to write generic arrow functions in TypeScript, how their syntax compares to regular generic functions, where they are commonly used, and which mistakes beginners often make when combining generics, arrow functions, and type annotations.
Concept
Generics in TypeScript let you write functions that work with many types while still preserving type safety.
For example, this regular function:
function identity<T>(arg: T): T {
return arg;
}
says:
Tis a type placeholder- whatever type comes in as
arg - the same type comes back out
This is useful because the function is reusable without losing information about types.
Arrow functions support generics too. The generic type parameter is written before the parameter list:
const identity = <T>(arg: T): T => {
return arg;
};
Here is the structure:
const functionName = <T>(param: T): T => {
// logic
};
This matters in real programming because arrow functions are used everywhere in modern TypeScript code:
- utility functions
- callbacks
- React code
- functional patterns like
map,filter, andreduce - small reusable helpers
So if you know generics but only for function declarations, learning the arrow version helps you write the same type-safe logic in the style most codebases use today.
Mental Model
Think of a generic as a label slot on a machine.
- A normal function machine can have a slot labeled
T - An arrow function machine can have the same slot
- You plug in a type when you use it, and the machine keeps that type consistent
So this:
function identity<T>(arg: T): T
and this:
const identity = <T>(arg: T): T =>
are just two differently shaped machines with the same type slot.
The important idea is: the generic belongs to the function itself, not to the variable name.
Syntax and Examples
Basic syntax
A generic arrow function in TypeScript looks like this:
const identity = <T>(arg: T): T => {
return arg;
};
This is the arrow-function version of:
function identity<T>(arg: T): T {
return arg;
}
Example: identity function
const identity = <T>(arg: T): T => arg;
const a = identity<string>("hello");
const b = identity<number>(42);
const c = identity(true);
What happens here?
identity<string>("hello")returns astringidentity<number>(42)returns anumberidentity(true)lets TypeScript infer as
Step by Step Execution
Consider this example:
const identity = <T>(arg: T): T => arg;
const value = identity("TypeScript");
Step by step:
identityis assigned an arrow function.<T>declares a generic type parameter namedT.(arg: T)means the parameterargmust be of typeT.: Tafter the parameter list means the function returns the same typeT.=> argreturns the argument unchanged.- When calling
identity("TypeScript"), TypeScript infers thatTisstring. - So the function becomes effectively:
const value: string = ();
Real World Use Cases
Generic arrow functions appear often in practical TypeScript code.
1. Reusable utility helpers
const toArray = <T>(value: T): T[] => [value];
Useful for data transformation utilities.
2. Safe data selection
const getFirst = <T>(items: T[]): T | undefined => items[0];
Common in list processing, API data handling, and UI state logic.
3. Wrapping values in objects
const createResponse = <T>(data: T) => ({ data, success: true });
Useful in APIs, services, and helper layers.
4. Generic event or callback helpers
const callTwice = <T>(value: T, fn: (item: T) => void): void => {
fn(value);
fn(value);
};
Real Codebase Usage
In real codebases, generic arrow functions are usually used for small, composable helpers rather than large standalone functions.
Common patterns
Guard-style transformation helpers
const ensureArray = <T>(value: T | T[]): T[] => {
return Array.isArray(value) ? value : [value];
};
This pattern normalizes input into a predictable shape.
Data mapping helpers
const pluck = <T, K extends keyof T>(obj: T, key: K): T[K] => obj[key];
This is common when working with objects and typed configuration.
Validation wrappers
const withDefault = <T>(value: T | undefined, fallback: T): T => {
return value === undefined ? fallback : value;
};
Useful in configuration loading and API parsing.
Generic callbacks stored in constants
const identity = <T>(x: T): x;
Common Mistakes
1. Putting the generic in the wrong place
Incorrect:
const identity = (arg: T): T => arg;
Problem:
Tis used, but never declared
Correct:
const identity = <T>(arg: T): T => arg;
2. Confusing variable type annotation with function generics
You may also see this style:
const identity: <T>(arg: T) => T = (arg) => arg;
This is valid, but it means:
- the variable
identityis given a generic function type - the implementation is assigned to that variable
Beginners often mix this up with the direct syntax.
Direct syntax is usually easier to read:
const identity = <T>(: T): arg;
Comparisons
Generic regular function vs generic arrow function
| Style | Syntax | Best for |
|---|---|---|
| Regular function | function identity<T>(arg: T): T { return arg; } | Named reusable functions, hoisting, clearer declarations |
| Arrow function | const identity = <T>(arg: T): T => arg; | Utilities, callbacks, modern const-based code style |
Direct generic arrow syntax vs typed variable syntax
| Approach | Example | Notes |
|---|---|---|
| Generic on the arrow function | const fn = <T>(arg: T): T => arg; | Usually easiest to read |
| Generic on the variable type |
Cheat Sheet
Generic arrow function syntax
const fn = <T>(arg: T): T => {
return arg;
};
Multiple type parameters
const fn = <T, U>(a: T, b: U): [T, U] => [a, b];
Constraint syntax
const fn = <T extends { length: number }>(value: T): number => value.length;
Generic function type on a variable
const fn: <T>(arg: T) => T = (arg) => arg;
In .tsx files
Prefer:
const fn = <T,>(arg: T): => arg;
FAQ
What is the syntax for a generic arrow function in TypeScript?
Use this pattern:
const identity = <T>(arg: T): T => arg;
Can TypeScript infer the generic type in an arrow function?
Yes. In many cases you do not need to write the type argument explicitly.
const result = identity(123);
Here, T is inferred as number.
Why does <T> sometimes fail in a .tsx file?
Because the parser may interpret <T> as JSX instead of a generic type parameter. A common fix is:
const identity = <T,>(arg: T): T => arg;
Is a generic arrow function different from a generic regular function?
Not in capability. Both can use generics. The main difference is syntax and how they behave with things like this and hoisting.
Can arrow functions have more than one generic type?
Mini Project
Description
Build a small set of generic arrow-function utilities in TypeScript. This project demonstrates how generic arrow functions can safely work with different types while preserving accurate return types. It reflects the kind of small helper functions developers often write in real projects.
Goal
Create and use several generic arrow functions that work with strings, numbers, arrays, and objects without losing type safety.
Requirements
- Create a generic arrow function that returns the input unchanged.
- Create a generic arrow function that wraps a value in an array.
- Create a generic arrow function that returns the first item of an array.
- Create a generic arrow function that reads a value from an object using a typed key.
- Call each function with real examples and log the results.
Keep learning
Related questions
Angular formGroup Error Explained: Fixing 'Can't bind to formGroup' in Reactive Forms
Learn why Angular shows 'Can't bind to formGroup' and how to fix it by importing ReactiveFormsModule correctly.
Fix "Element implicitly has an 'any' type" in TypeScript Object Indexing
Learn why TypeScript rejects string object indexing and how to fix it with keyof, unions, and typed object keys in React.
Fix "Property has no initializer" in Angular TypeScript Components
Learn why Angular TypeScript shows "Property has no initializer" and how to fix it using defaults, optional properties, or definite assignment.