Saltar al contingut principal
Tornar enrere

TypeScript #8: Generics (El bàsic)

#typescript #generics #basics

L'eina més potent de TS. Aprèn a escriure codi reutilitzable i flexible amb <T>.

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).

typescript
// 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

La 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”.

typescript
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 string

La 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.

typescript
// 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.

tsx
// 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"].