Что такое дженерики (generics) в TypeScript?

MiddleTypeScript #typescript #generics

Вопрос

Зачем нужны дженерики в TypeScript и как их использовать?

Короткий ответ

Дженерики позволяют писать функции, классы и типы, которые работают с разными типами данных, сохраняя при этом типобезопасность — вместо any мы получаем связь между входным и выходным типом.

Подробный ответ

Без дженериков пришлось бы либо дублировать код под каждый тип, либо использовать any, теряя проверку типов. Дженерик-параметр (обычно T) — это "переменная типа", которая подставляется при вызове.

function identity<T>(value: T): T {
  return value
}

identity<string>('hello') // T = string
identity(42)               // T выведется автоматически как number

Дженерики часто ограничивают через extends:

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key]
}

Здесь K extends keyof T гарантирует, что key — это существующее свойство объекта T, и TypeScript выведет корректный тип возвращаемого значения.

Пример

interface ApiResponse<TData> {
  data: TData
  error: string | null
}

async function fetchJson<TData>(url: string): Promise<ApiResponse<TData>> {
  const res = await fetch(url)
  return { data: await res.json(), error: null }
}

interface User { id: number; name: string }

const { data } = await fetchJson<User>('/api/user/1')
data.name // TypeScript знает, что это string

Дополнительные вопросы

  • Как ограничить дженерик конкретным набором типов?
  • Что такое дженерики по умолчанию (<T = string>)?
  • Чем дженерики отличаются от union-типов?