Generics TypeScript с примерами

Generics TypeScript — это мощная функция, которая позволяет создавать повторно используемые и типобезопасные компоненты. Generics предоставляют способ создания классов, функций и интерфейсов, которые работают с различными типами, сохраняя при этом сильную типобезопасность. Эта статья познакомит вас с generics и продемонстрирует, как их использовать, на практических примерах.

Понимание дженериков

Generics позволяют вам определить компонент с заполнителем для типа, с которым он работает. Вместо указания конкретного типа вы используете параметр generic-типа, который можно заменить любым типом при использовании компонента.

Базовый синтаксис

Базовый синтаксис для определения универсального типа — использование угловых скобок <> с именем параметра типа. Вот простой пример:

function identity(value: T): T {
  return value;
}

const stringIdentity = identity("Hello"); // string
const numberIdentity = identity(123); // number

В этом примере identity — это общая функция, которая принимает параметр value типа T и возвращает значение того же типа. Параметр типа T заменяется фактическим типом при вызове функции.

Дженерики с классами

Generics также можно использовать с классами для создания гибких и повторно используемых структур данных. Вот пример generic-класса:

class Box {
  private value: T;

  constructor(value: T) {
    this.value = value;
  }

  getValue(): T {
    return this.value;
  }
}

const stringBox = new Box("TypeScript");
console.log(stringBox.getValue()); // Output: TypeScript

const numberBox = new Box(42);
console.log(numberBox.getValue()); // Output: 42

В этом примере класс Box определен с параметром универсального типа T. Класс имеет частное свойство value типа T и метод getValue, который возвращает значение типа T.

Дженерики с интерфейсами

Generics можно использовать с интерфейсами для создания гибких и типобезопасных интерфейсов. Вот пример:

interface Pair<T, U> {
  first: T;
  second: U;
}

const pair: Pair<string, number> = {
  first: "Age",
  second: 30
};

console.log(pair.first); // Output: Age
console.log(pair.second); // Output: 30

В этом примере интерфейс Pair определен с двумя параметрами общего типа T и U. Интерфейс представляет собой пару значений с типами T и U соответственно.

Дженерики в функциях

Обобщения могут использоваться в функциях для обработки нескольких типов, сохраняя при этом безопасность типов. Вот пример обобщенной функции, которая работает с массивами:

function reverseArray(items: T[]): T[] {
  return items.reverse();
}

const reversedStringArray = reverseArray(["one", "two", "three"]);
console.log(reversedStringArray); // Output: ["three", "two", "one"]

const reversedNumberArray = reverseArray([1, 2, 3]);
console.log(reversedNumberArray); // Output: [3, 2, 1]

В этом примере функция reverseArray принимает массив типа T и возвращает обратный массив того же типа. Параметр типа T гарантирует, что функция работает с массивами любого типа, сохраняя безопасность типов.

Ограничения на дженерики

Иногда может потребоваться наложить ограничения на параметр универсального типа, чтобы гарантировать, что он имеет определенные свойства. Это делается с помощью ограничений:

function logLength(item: T): void {
  console.log(item.length);
}

logLength("Hello, TypeScript"); // Output: 16
logLength([1, 2, 3]); // Output: 3
// logLength(123); // Error: number does not have a length property

В этом примере функция logLength ограничена типами, имеющими свойство length. Это позволяет функции принимать строки и массивы, но не числа или другие типы без свойства length.

Заключение

Generics в TypeScript предоставляют мощный способ создания гибких и повторно используемых компонентов, сохраняя при этом сильную безопасность типов. Понимая и используя generics, вы можете писать более универсальный и адаптируемый код, улучшая общее качество и удобство обслуживания ваших приложений TypeScript.

Поэкспериментируйте с дженериками в своих проектах, чтобы увидеть их преимущества на практике и улучшить свои навыки программирования на TypeScript.