Обобщения в TypeScript
В этой статье объясняются обобщения в TypeScript.
YouTube Video
Обобщения в TypeScript
Обобщения в TypeScript — это функция, которая позволяет определять многократно используемые и типобезопасные функции, классы и интерфейсы с помощью параметризации типов. Использование обобщений позволяет писать код, который не зависит от конкретных типов, позволяя выполнять одинаковые операции с разными типами.
Основы обобщений
Обобщения работают как шаблоны, принимающие типы в качестве аргументов, что позволяет функциям и классам обрабатывать разные типы.
Обобщенные функции
Ниже приведен пример функции с типами её аргументов, заданными с использованием обобщений.
1function identity<T>(value: T): T {
2 return value;
3}
4
5console.log(identity<number>(42)); // 42
6console.log(identity<string>("Hello")); // Hello
T
— это параметр типа, который представляет типы аргументов функции и её возвращаемого значения. Фактический тип определяется при вызове функции.- Указывая явно
<number>
или<string>
, вы задаёте тип.
Обобщенные типы работают и без явного указания, так как TypeScript выполняет вывод типов.
1function identity<T>(value: T): T {
2 return value;
3}
4
5console.log(identity(42)); // 42
6console.log(identity("Hello")); // Hello
Ограничения для обобщений
Добавляя ограничения для обобщений, вы можете ограничить их приём только определённых типов.
1function loggingIdentity<T extends { length: number }>(arg: T): T {
2 console.log(arg.length);
3 return arg;
4}
5
6loggingIdentity("Hello"); // 5
7loggingIdentity([1, 2, 3]); // 3
8
9// loggingIdentity(42); // Error: number does not have a length property.
- Указание
T extends { length: number }
означает, чтоT
должен быть типом, содержащим свойствоlength
. Следовательно, типы без свойстваlength
не будут приниматься.
Обобщенные классы
Классы также можно определять, используя обобщения. Обобщенные классы предоставляют гибкие типы для свойств и методов.
1class Box<T> {
2 private _value: T;
3
4 constructor(value: T) {
5 this._value = value;
6 }
7
8 public getValue(): T {
9 return this._value;
10 }
11
12 public setValue(value: T): void {
13 this._value = value;
14 }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue()); // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue()); // Hello
Box<T>
объявляет типT
, используемый внутри класса, в качестве обобщения. Это позволяет переиспользовать тот же класс для различных типов.
Обобщенные интерфейсы
Обобщения также можно использовать с интерфейсами.
1interface Pair<T, U> {
2 first: T;
3 second: U;
4}
5
6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
7console.log(numberStringPair); // { first: 1, second: 'One' }
8
9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair); // { first: true, second: [ 1, 2, 3 ] }
- Указав два обобщенных типа с помощью
Pair<T, U>
, вы можете определить объект с комбинацией различных типов.
Аргументы типов по умолчанию
Также можно задать тип по умолчанию для параметров обобщённого типа.
1function createArray<T = string>(length: number, value: T): T[] {
2 return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a")); // ['a', 'a', 'a']
6console.log(createArray(3, 100)); // [100, 100, 100]
- Мы устанавливаем аргумент типа по умолчанию как
string
с помощью<T = string>
. Если тип не указан явно,T
будет иметь типstring
.
Обобщённые псевдонимы типов
Обобщённые типы также могут использоваться в качестве псевдонимов типов (type
).
1type Result<T> = {
2 success: boolean;
3 data: T;
4};
5
6const successResult: Result<number> = { success: true, data: 42 };
7const errorResult: Result<string> = { success: false, data: "Error occurred" };
8
9console.log(successResult); // { success: true, data: 42 }
10console.log(errorResult); // { success: false, data: 'Error occurred' }
Result<T>
представляет объект результата, содержащий данные типаT
. Таким образом, вы можете создавать гибкие псевдонимы типов, используя обобщения.
Несколько обобщённых типов
Используя несколько обобщённых типов, вы можете определить ещё более универсальные функции и классы.
1function merge<T, U>(obj1: T, obj2: U): T & U {
2 return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged); // { name: 'Alice', title: 'Engineer' }
- Функция
merge
принимает два разных типаT
иU
и объединяет их, возвращая новый объект.
Резюме
- Обобщения позволяют создавать многократно используемый и типобезопасный код, рассматривая типы как параметры.
- Используя обобщения в функциях, классах и интерфейсах, вы можете писать гибкую логику, работающую с различными типами.
- Добавляя ограничения к параметрам типов или задавая аргументы типов по умолчанию, вы можете контролировать область использования обобщений.
Используя обобщения, вы можете писать независимый от типов, универсальный код, максимально используя мощную систему типов TypeScript.
Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.