Generyki <T>

Typy i funkcje z parametrem typu, działające dla wielu typów bez utraty precyzji.

Na tej stronie

Przykład

#
TypeScript
function first<T>(items: T[]): T | undefined {
  return items[0]
}

const name = first(['Ania', 'Kuba'])
// const name: string | undefined
const course = first([{ title: 'HTML', modules: 11 }])
// const course: { title: string; modules: number } | undefined

console.log(name?.toUpperCase())
console.log(course?.modules)
Wynik
ANIA
11

Definicja i zastosowanie

#

Generyk to typ z parametrem, zapisywanym w nawiasach ostrych: <T>. Pozwala napisać funkcję, klasę albo typ raz, a używać go z różnymi typami danych, zachowując pełne informacje o typie.

Bez generyków funkcja zwracająca pierwszy element tablicy musiałaby zwracać any albo unknown. Z generykiem function first<T>(items: T[]): T | undefined kompilator wie, że dla tablicy napisów wynik to napis, a dla tablicy kursów obiekt kursu.

Najczęściej parametr typu jest wnioskowany z argumentów, więc nie musisz go podawać. Jawnie wpisujesz go wtedy, gdy nie da się go wywnioskować, na przykład useState<string | null>(null).

Składnia

#
Składnia
function nazwa<T>(param: T): T { … }
type Pudelko<T> = { value: T }

Więcej przykładów

#
Generyczny typ odpowiedzi API
TypeScript
type ApiResponse<T> = { ok: true; data: T } | { ok: false; error: string }

function unwrap<T>(response: ApiResponse<T>, fallback: T): T {
  return response.ok ? response.data : fallback
}

const levels: ApiResponse<number[]> = { ok: true, data: [1, 2, 3] }
const failed: ApiResponse<number[]> = { ok: false, error: 'timeout' }

console.log(unwrap(levels, []))
console.log(unwrap(failed, []))
Wynik
[1, 2, 3]
[]

Dobre praktyki

#
  • Nazwy parametrów typu mogą być opisowe, np. <TItem>, gdy jest ich kilka. Pojedyncze T jest w porządku przy prostych funkcjach.
  • Jeśli parametr typu pojawia się tylko raz w sygnaturze, prawdopodobnie nie jest potrzebny.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.