Шаблоны дженериков, к которым вы прибегаете чаще всего, сгруппированные по задаче: объявить параметр типа, ограничить его, задать значение по умолчанию, ветвить условным типом, захватить через infer и отобразить форму. Каждая строка сопоставляет шаблон с однострочным примером.
Дженерик — это параметр типа: заполнитель для типа, который выбирает вызывающий, поэтому одна функция или тип подходит для многих форм без потери точности. Читайте <T> как «для некоторого типа T». Сила заключается в ограничении T, ветвлении по нему и отображении его. Шаблоны ниже — рабочий словарь.
Справочная таблица · 28 записи
Дженерики TypeScriptExplained
28 of 28 rows
Объявление
Параметр типа, который выбирает вызывающий.
function first<T>(xs: T[]): T
Несколько независимых параметров типа.
function pair<T, U>(a: T, b: U): [T, U]
Второй параметр, связанный с ключами первого.
function get<T, K extends keyof T>(o: T, k: K): T[K]
Класс с параметром типа в полях и методах.
class Box<T> { value: T }
Форма объекта с параметром типа.
interface Result<T> { data: T }
Параметр типа в стрелочной функции; запятая в конце не даёт файлам .tsx прочитать его как JSX.
const first = <T,>(xs: T[]): T => xs[0]
Ограничение
Требует, чтобы T был присваиваем к Type.
function len<T extends { length: number }>(x: T)
Ограничивает T ключом другого типа.
type Keys<O> = keyof O
Ограничивает T конструируемым классом.
function make<C extends new () => C>(c: C): C
Требует, чтобы T удовлетворял нескольким ограничениям одновременно.
function log<T extends Error & { code: number }>(e: T)
Ограничивает чем угодно; сохраняет параметр универсальным, не сужая его.
type Wrap<T> = T extends unknown ? { v: T } : never
По умолчанию и infer
Даёт T значение по умолчанию, если вызывающий его не указал.
function parse<T = string>(): T
Захватывает тип внутри условного.
type El<T> = T extends Array<infer I> ? I : never
Разворачивает вложенный Promise до его внутреннего типа.
type Data = Awaited<Promise<User>>
Захватывает один фрагмент типа шаблонного литерала.
type Path<S> = S extends `/api/${infer R}` ? R : never
Проверяет всё объединение сразу; голый T выводит по одному члену за раз.
type El<T> = [T] extends [Array<infer I>] ? I : never
Условные и отображаемые
Выбирает тип в зависимости от того, присваиваем ли T к U.
type IsStr<T> = T extends string ? true : false
Строит новый тип объекта, преобразуя каждый ключ T.
type Frozen<T> = { [K in keyof T]: Readonly<T[K]> }
Объект, ключи которого — K, а значения — V.
type Scores = Record<string, number>
Встроенные дженерики, производные от шаблонов выше.
type Preview = Pick<User, "id" | "name">
Голый T перед extends выполняется один раз на член объединения и объединяет результаты.
ToArray<'a' | 'b'> = 'a'[] | 'b'[]
Добавляет или убирает модификаторы у отображённых ключей.
type Req<T> = { [K in keyof T]-?: T[K] }
Ключи значения времени выполнения, как тип.
const opts = { a: 1 }; type K = keyof typeof opts
Строит строковый тип из других строковых типов.
type Route = `/users/${string}`
Соединяет типы-кортежи встык.
type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U]
Тип, чьё определение ссылается на себя.
type Json = string | number | Json[] | { [k: string]: Json }
Проверяет значение против типа и сохраняет его более узкий литеральный тип.
const c = { dark: "#000" } satisfies Record<string, string>
Сохраняет литеральный тип вызывающего вместо расширения (TS 5.0).