dev3 ·
I see functions like function first<T>(arr: T[]): T and Promise<User>. What problem do generics solve and how do I constrain them?
0
DEV3 Developer Forum
Every post is reviewed first. Usually reviewed within 24 hours.
I see functions like function first<T>(arr: T[]): T and Promise<User>. What problem do generics solve and how do I constrain them?
Generics let a function, type or class work with many types while keeping the relationship between input and output types.
function first(arr: any[]): any { return arr[0]; } // loses information
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const n = first([1, 2, 3]); // number | undefined
const s = first(['a', 'b']); // string | undefined
T is a type parameter inferred from the argument. You can also pass it explicitly: first<number>([1]).
function getLength<T extends { length: number }>(x: T): number {
return x.length;
}
getLength('abc'); // ok
getLength(42); // error
function pick<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
pick({ id: 1, name: 'a' }, 'name'); // string
pick({ id: 1 }, 'nope'); // compile error
type ApiResponse<T = unknown> = { data: T; error?: string };
type Page<T> = { items: T[]; total: number };
async function get<T>(url: string): Promise<ApiResponse<T>> {
const res = await fetch(url);
return res.json();
}
const r = await get<Page<User>>('/api/users');
Note that res.json() is unchecked: the generic is a promise to the compiler, not validation.
Partial<T>, Required<T>, Pick<T, K>, Omit<T, K>, Record<K, V>, ReturnType<typeof fn>, Awaited<T>.
.tsx files arrow generics need a trailing comma or constraint: <T,>(x: T) => x.