Ответ вслух Middle Дженерики обновлено

Типизация groupBy

Вопрос

Как бы вы типизировали функцию groupBy(items, getKey), которая группирует массив по ключу?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Нужны два параметра. T это тип элемента, он выводится из массива.

Что должно прозвучать в ответе

  • Параметр `T` для элемента массива, выводится из `items`

  • Параметр `K extends PropertyKey` для ключа, выводится из результата `getKey`

  • Результат `Partial<Record<K, T[]>>` или `Record<K, T[]>` с оговоркой: не все ключи обязаны встретиться

  • Сравнение с встроенным `Object.groupBy` (ES2024), который возвращает `Partial<Record<K, T[]>>`

  • Проверка на примере: объединение литералов ключей сохраняется

Что могут спросить следом

  • Почему Partial, а не просто Record?
  • Что будет, если ключ это объект?
  • Как вариант с Map типизировать?

Разбор

Нужны два параметра. T это тип элемента, он выводится из массива. K extends PropertyKey это тип ключа, он выводится из того, что возвращает getKey: если колбэк возвращает 'admin' | 'user', то и ключи результата будут этими литералами. Сигнатура: function groupBy<T, K extends PropertyKey>(items: T[], getKey: (item: T) => K): Partial<Record<K, T[]>>. Partial честнее, чем Record: если ни одного админа нет, ключа admin в объекте не будет, и result.admin должен иметь тип T[] | undefined. Именно так типизирован встроенный Object.groupBy из ES2024. Если ключом нужен объект, беру Map.groupBy, он возвращает Map<K, T[]>.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме