tgoop.com/prog_way_blog/260
Last Update:
Дженерики
Сколько я не бился в попытках объяснить что такое дженерик, кажется, что эта тема многим даётся тяжело. В этом канале я планирую написать несколько постов на эту тему, в которых разберу самые частые варианты использования дженериков на практике начиная от легкого к сложному. И начнем с самого простого:
Generic Type — обобщённый тип — это тип, который позволяет создавать по своему подобию другие типы или же динамически вычислять типы в зависимости от входных данных. Тут я максимально отойду от какой-то академичности и приведу простую аналогию:
Тип — это переменная
Дженерик тип — это функция, которая возвращает тип
И дженерик типы называть функциями в корне неверно, зато такая аналогия для начала будет понятна большинству. Разберем на примере:
const name = "Denis"
const getPerson = (name) => ({
name,
type: "person"
})
const person = getPerson(name)
В этом примере у нас есть переменная, на основе которой мы можем получить некоторый объект
person
используя функцию getPerson
. А теперь рассмотрим нечто похожее в типах:type Status = "success" | "error"
type Response<T> = {
status: T,
message: string,
code: number,
}
type ApiResponse = Response<Status>
Уже в этом примере мы наблюдаем чем-то похожую ситуацию коду выше — мы создаём какую-то новую сущность на основе уже существующей. В первом случае — новый объект, а во втором — новый тип.
В таком контексте дженерики можно воспринимать как функции-конструкторы, которые, основываясь на некоторых входных параметрах, могут создавать новые типы. И из всего этого можно сделать вывод, что дженерики — это конструкторы типов.
На этом моменте у многих новичков часто возникает закономерный вопрос — а зачем их использовать? И ответ на него очень прост — почти за тем же, что и обычные функции.
Дженерик типы позволяют не дублировать код, а выносить некоторые общие части, чтобы далее их переиспользовать. Попробуем написать уже такой код, что легко встретится на практике:
// объявим сущности приложения
type User = {
name: string,
age: number,
}
type Task = {
completed: boolean,
title: string,
}
// ответ api в случае ошибки
type ResponseError = {
code: number;
message: string;
}
// ответ api в случае успеха
type ListResponseSuccess<T> = {
data: T[],
total: number;
}
// общий тип со всеми возможными
// состояниями ответа
type ListResponse<T> = ListResponseSuccess<T> | ResponseError
// типы для наших сущностей
type UserListResponse = ListResponse<User>
type TaskListReponse = ListResponse<Task>
// и их может быть сколько угодно...
type CarListResponse = ListResponse<Car>
type RoleListResponse = ListResponse<Role>
type UserGroupListResponse = ListResponse<UserGroup>
// и тд
В этом случае мы создали тип конструктор
ListResponse
, который в дальнейшем сможем использовать для типизации всего нашего API без лишнего дублирования общих частей.Это самый базовый пример использования дженериков, который может встретиться на практике. Не забывайте, что дженерики есть не только у типов, а и у интерфейсов, классов, функций… Даже у React-компонентов и хуков (что в целом тоже либо класс либо функция).
Примеры с другими сущностями тоже хотелось бы показать, но уже в рамках других постов.
Спасибо за прочтение, это важно для меня ❤️
#web #theory #typescript
BY progway — программирование, IT

Share with your friend now:
tgoop.com/prog_way_blog/260