Fins ara, els nostres tipus eren fixos. string és sempre string.
Però, i si volem crear una funció o un component que funcioni amb qualsevol tipus, però sense perdre la seguretat?
Aquí entren els Generics. Són com “paràmetres” però per a Tipus.
El Problema: Duplicació o any
Imaginem una funció que retorna el que li passes (clàssica funció identity).
// Opció 1: Duplicar codi per a cada tipus
function returnString(val: string): string { return val; }
function returnNumber(val: number): number { return val; }
// Opció 2: Usar 'any' (Perdem el tipus)
function returnAny(val: any): any { return val; }
const resultat = returnAny("Hola");
// TS no sap que 'resultat' és string, creu que és 'any'.
// resultat.toUpperCase(); // ❌ No autocompleta// Opció 1: Duplicar codi per a cada tipus
function returnString(val: string): string { return val; }
function returnNumber(val: number): number { return val; }
// Opció 2: Usar 'any' (Perdem el tipus)
function returnAny(val: any): any { return val; }
const resultat = returnAny("Hola");
// TS no sap que 'resultat' és string, creu que és 'any'.
// resultat.toUpperCase(); // ❌ No autocompletaLa Solució: Generics <T>
Podem dir-li a la funció: “Escolta, et passarem un tipus al qual direm T. Usa’l per tipar l’argument i el retorn”.
function identity<T>(val: T): T {
return val;
}
// Ús explícit (li passem el tipus)
const num = identity<number>(123); // num és number
// Inferència (TS és llest i ho endevina)
const str = identity("Hola"); // str és "Hola" (literal) o stringfunction identity<T>(val: T): T {
return val;
}
// Ús explícit (li passem el tipus)
const num = identity<number>(123); // num és number
// Inferència (TS és llest i ho endevina)
const str = identity("Hola"); // str és "Hola" (literal) o stringLa T és una convenció (ve de Type), però podem dir-li com vulguem: <Data>, <Response>, <Props>.
Interfícies Genèriques
Això és súper comú en React o respostes d’API.
// Una caixa que pot contenir qualsevol COSA
interface Caixa<T> {
contingut: T;
etiqueta: string;
}
const caixaDeSabates: Caixa<string> = {
contingut: "Nike Air",
etiqueta: "Esports"
};
const caixaDeRegal: Caixa<number> = {
contingut: 1000,
etiqueta: "Diners"
};// Una caixa que pot contenir qualsevol COSA
interface Caixa<T> {
contingut: T;
etiqueta: string;
}
const caixaDeSabates: Caixa<string> = {
contingut: "Nike Air",
etiqueta: "Esports"
};
const caixaDeRegal: Caixa<number> = {
contingut: 1000,
etiqueta: "Diners"
};Exemple Real: useState
Si hem usat React, ja hem usat Generics sense saber-ho.
// useState és una funció Genèrica: function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>]
// Inferència:
const [name, setName] = useState("Alice"); // TS infereix que T és string
// Explícit (útil quan el valor inicial és null):
const [user, setUser] = useState<Usuari | null>(null);// useState és una funció Genèrica: function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>]
// Inferència:
const [name, setName] = useState("Alice"); // TS infereix que T és string
// Explícit (útil quan el valor inicial és null):
const [user, setUser] = useState<Usuari | null>(null);Provem-ho!
Crea una funció envolver que posis el que posis, t’ho retorni dins d’un array.
Si poses 10, surt [10]. Si poses "hola", surt ["hola"].