Generic functions are functions that can work with different data types while maintaining type safety. Instead of creating separate functions for every data type, you can create one reusable function using a generic type parameter.
A generic function uses a type parameter so that the function can work with different types.
function identity<T>(
value: T
): T {
return value;
}
Here, T represents the type of the value.
Generic functions allow you to reuse the same function with multiple data types.
function identity<T>(
value: T
): T {
return value;
}
const name = identity("Amit");
const age = identity(25);
One function can handle both strings and numbers.
The generic type parameter is usually written inside angle brackets after the function name.
function display<T>(
value: T
): T {
return value;
}
T is a placeholder for a real type.
function identity<T>(
value: T
): T {
return value;
}
const result =
identity<string>("Hello");
console.log(result);
In this example, T is explicitly set to
string.
function identity<T>(
value: T
): T {
return value;
}
const result =
identity<number>(100);
console.log(result);
Here, T is explicitly set to
number.
TypeScript can often determine the generic type automatically from the function argument.
function identity<T>(
value: T
): T {
return value;
}
const name =
identity("Rahul");
const age =
identity(30);
You do not always need to write <string>
or <number> explicitly.
function identity<T>(
value: T
): T {
return value;
}
const result =
identity(true);
console.log(result);
The type parameter T becomes
boolean.
function getFirst<T>(
items: T[]
): T {
return items[0];
}
const number =
getFirst([10, 20, 30]);
const name =
getFirst(["Amit", "Rahul"]);
The function works with arrays of different types.
function createArray<T>(
value: T
): T[] {
return [value];
}
const numbers =
createArray(10);
const names =
createArray("Amit");
The returned array keeps the type of the supplied value.
function pair<T>(
first: T,
second: T
): T[] {
return [first, second];
}
const numbers =
pair(10, 20);
const names =
pair("Amit", "Rahul");
Both arguments use the same generic type.
A generic function can use multiple type parameters.
function createPair<T, U>(
first: T,
second: U
) {
return {
first,
second
};
}
const result =
createPair("Amit", 25);
console.log(result);
function createObject<T>(
value: T
) {
return {
value
};
}
const result =
createObject("TypeScript");
console.log(
result.value
);
function getName<T extends {
name: string
}>(user: T): string {
return user.name;
}
const student = {
name: "Amit",
age: 20
};
console.log(
getName(student)
);
The constraint ensures that the object has a
name property.
Use extends when a generic function requires
certain properties or capabilities.
function getLength<
T extends { length: number }
>(value: T): number {
return value.length;
}
console.log(
getLength("Hello")
);
console.log(
getLength([1, 2, 3])
);
interface HasId {
id: number;
}
function showId<
T extends HasId
>(item: T): number {
return item.id;
}
const student = {
id: 101,
name: "Amit"
};
console.log(
showId(student)
);
The keyof operator allows a generic function
to work safely with object properties.
function getProperty<
T,
K extends keyof T
>(
object: T,
key: K
): T[K] {
return object[key];
}
const student = {
name: "Amit",
age: 20
};
const name =
getProperty(student, "name");
const age =
getProperty(student, "age");
function display<T>(
value: T
): T {
return value;
}
const result =
display<string | number>(
"Hello"
);
console.log(result);
A generic type parameter can also be explicitly assigned a union type.
Generic functions can also be used with callback functions.
function processValue<T>(
value: T,
callback: (value: T) => void
): void {
callback(value);
}
processValue(
"Hello",
value => {
console.log(
value.toUpperCase()
);
}
);
function createPromise<T>(
value: T
): Promise<T> {
return Promise.resolve(value);
}
const promise =
createPromise("Hello");
promise.then(value => {
console.log(
value.toUpperCase()
);
});
The promise preserves the generic type of the value.
interface ApiResponse<T> {
data: T;
success: boolean;
}
function createResponse<T>(
data: T
): ApiResponse<T> {
return {
data,
success: true
};
}
const response =
createResponse("Student loaded");
console.log(
response.data
);
interface Student {
id: number;
name: string;
}
function createStudentResponse<T>(
data: T
): T {
return data;
}
const student: Student = {
id: 101,
name: "Amit"
};
const result =
createStudentResponse(student);
console.log(
result.name
);
function findItem<T>(
items: T[],
condition: (item: T) => boolean
): T | undefined {
return items.find(condition);
}
const students = [
{
id: 1,
name: "Amit"
},
{
id: 2,
name: "Rahul"
}
];
const student =
findItem(
students,
item => item.id === 2
);
console.log(student);
function mapItems<T, U>(
items: T[],
callback: (item: T) => U
): U[] {
return items.map(callback);
}
const numbers = [
1, 2, 3
];
const strings =
mapItems(
numbers,
number => String(number)
);
console.log(strings);
Here, T represents the input type and
U represents the output type.
Generic functions can be used inside React applications to create reusable type-safe logic.
function getFirst<T>(
items: T[]
): T {
return items[0];
}
const names =
["Amit", "Rahul"];
const firstName =
getFirst(names);
Generic functions are useful in React Native when working with reusable data-processing functions.
function getFirstItem<T>(
items: T[]
): T {
return items[0];
}
const users = [
{
id: 1,
name: "Amit"
},
{
id: 2,
name: "Rahul"
}
];
const firstUser =
getFirstItem(users);
console.log(
firstUser.name
);
A generic function can define a default type parameter.
function createValue<
T = string
>(
value: T
): T {
return value;
}
const text =
createValue("Hello");
const number =
createValue<number>(100);
Generic functions can preserve the types of multiple values inside a tuple.
function makePair<T, U>(
first: T,
second: U
): [T, U] {
return [first, second];
}
const result =
makePair(
"Amit",
25
);
console.log(result);
any when a generic type would be safer.interface Student {
id: number;
name: string;
course: string;
}
function findStudent<T extends {
id: number
}>(
students: T[],
id: number
): T | undefined {
return students.find(
student =>
student.id === id
);
}
const students: Student[] = [
{
id: 101,
name: "Amit",
course: "TypeScript"
},
{
id: 102,
name: "Rahul",
course: "React Native"
}
];
const student =
findStudent(
students,
102
);
if (student) {
console.log(
"Name:",
student.name
);
console.log(
"Course:",
student.course
);
}
This example uses a generic constraint to create a reusable student-search function.
Generic functions allow you to create reusable functions that work with different types while preserving type safety.
function identity<T>(
value: T
): T {
return value;
}
const name =
identity("TypeScript");
const age =
identity(25);
const active =
identity(true);
Generic functions are an important foundation for advanced TypeScript programming and are widely used when building React and React Native applications.
T is commonly used as a generic type parameter.T and U can be used.extends.keyof can be combined with generic functions.Question: Which syntax is commonly used to define a generic type parameter in a TypeScript function?