TypeScript - Ж_generics: Введение для начинающих
Привет, будущий супергерой кодирования! Сегодня мы отправляемся в увлекательное путешествие в мир обобщённых типов TypeScript. Не волнуйтесь, если вы новички в программировании – я буду вашим дружелюбным проводником, и мы будем двигаться шаг за шагом. К концу этого руководства вы будете использовать обобщённые типы, как профи!
Что такое обобщённые типы и почему нам это важно?
Прежде чем мы углубимся в детали, начнём с простой аналогии. Представьте, что у вас есть магическая коробка, которая может удерживать любой тип предметов. Иногда вы кладёте в неё книгу, иногда игрушку, или даже бутерброд. Вот что такое обобщённые типы в TypeScript – они позволяют нам создавать гибкий, повторно используемый код, который может работать с различными типами.
Примеры проблем
Давайте рассмотрим несколько сценариев, где обобщённые типы могут спасти положение:
- Вы хотите создать функцию, которая может反转 любой тип массива (числа, строки, объекты).
- Вам нужна класс, который может хранить и извлекать любой тип данных.
- Вы разрабатываете утилиту, которая должна работать с различными типами данных.
Без обобщённых типов вам пришлось бы писать separate функции или классы для каждого типа данных. Это много повторения, и как любой хороший программист знает, повторение – враг чистого кода!
TypeScript обобщённые типы на выручку!
Теперь, давайте натянем рукава и посмотрим, как работают обобщённые типы на практике.
Основная функция обобщённого типа
Вот пример простой функции обобщённого типа, которая может работать с любым типом:
function identity<T>(arg: T): T {
return arg;
}
Давайте разберём это:
-
<T>
– это наш параметр типа. Это как placeholder для типа, который мы будем использовать. -
(arg: T)
означает, что наша функция принимает аргумент типа T. -
: T
после скобок означает, что наша функция вернёт значение типа T.
Мы можем использовать эту функцию следующим образом:
let output1 = identity<string>("Привет, Обобщённые типы!");
let output2 = identity<number>(42);
console.log(output1); // "Привет, Обобщённые типы!"
console.log(output2); // 42
Круто, правда? Одна и та же функция работает с различными типами!
Обобщённый интерфейс
Мы также можем использовать обобщённые типы с интерфейсами. Вот пример:
interface GenericBox<T> {
contents: T;
}
let stringBox: GenericBox<string> = { contents: "Секретное сообщение" };
let numberBox: GenericBox<number> = { contents: 123 };
console.log(stringBox.contents); // "Секретное сообщение"
console.log(numberBox.contents); // 123
Наш GenericBox
может удерживать любой тип содержимого. Это как та магическая коробка, о которой мы говорили раньшe!
Обобщённые классы
Давайте создадим обобщённый класс, который может работать в качестве простого хранилища данных:
class DataStore<T> {
private data: T[] = [];
addItem(item: T): void {
this.data.push(item);
}
getItems(): T[] {
return this.data;
}
}
let stringStore = new DataStore<string>();
stringStore.addItem("Привет");
stringStore.addItem("Мир");
console.log(stringStore.getItems()); // ["Привет", "Мир"]
let numberStore = new DataStore<number>();
numberStore.addItem(1);
numberStore.addItem(2);
console.log(numberStore.getItems()); // [1, 2]
Этот класс DataStore
может хранить и извлекать любой тип данных. Pretty handy, huh?
Ограничения обобщённых типов
Иногда мы хотим ограничить типы, которые могут использоваться с нашими обобщёнными типами. Мы можем сделать это с помощью ограничений:
interface Lengthy {
length: number;
}
function logLength<T extends Lengthy>(arg: T): void {
console.log(arg.length);
}
logLength("Привет"); // 5
logLength([1, 2, 3]); // 3
logLength({ length: 10 }); // 10
// logLength(123); // Error: Number doesn't have a length property
Здесь наша функция logLength
может работать только с типами, которые имеют свойство length
.
Преимущества обобщённых типов
Теперь, когда мы видели обобщённые типы в действии, lets подвести их преимущества:
- Повторное использование кода: Написать один раз, использовать с множеством типов.
- Типовая безопасность: Catch ошибки, связанные с типом, на этапе компиляции.
- Гибкость: Создавать компоненты, которые могут работать с различными типами данных.
- Ясность: Делать очевидными взаимоотношения между входами и выходами.
Таблица методов обобщённых типов
Вот удобная таблица некоторых часто встречающихся обобщённых методов:
Метод | Описание | Пример |
---|---|---|
Array.map<U>() |
Преобразует элементы массива | [1, 2, 3].map<string>(n => n.toString()) |
Promise.all<T>() |
Ждёт завершения всех обетов | Promise.all<number>([Promise.resolve(1), Promise.resolve(2)]) |
Object.keys<T>() |
Получает ключи объекта в массиве | Object.keys<{name: string}>({name: "Alice"}) |
JSON.parse<T>() |
Пarsed JSON строку в объект | JSON.parse<{age: number}>('{"age": 30}') |
Заключение
Поздравляю! Вы только что сделали свои первые шаги в чудесный мир обобщённых типов TypeScript. Помните, как и любое мощное средство, обобщённые типы могут показаться немного сложными сначала, но с практикой они станут второй натурой.
Пока вы продолжаете своё путешествие в программировании, вы обнаружите, что обобщённые типы – это как швейцарский армейский нож в вашем наборе инструментов TypeScript – универсальный, мощный и невероятно полезный. Так что前进 и кодируйте, молодой падаван, и пусть обобщённые типы будут с вами!
Счастливого кодирования, и до следующего раза, продолжайте исследовать и учиться!
Credits: Image by storyset