Кастомные дженерики в TypeScript
Дженерики, или обобщённые типы в TypeScript. Компонент — один, а типы данных, с которыми он работает, — разные. Дженерики можно применять с функциями, интерфейсами и классами.
Generic Functions
В треугольных скобках указывается обобщённый тип, которому можно придумать любое название. Для упрощения используем букву T.
При объявлении функции это название не имеет значения, но оно должно указывать, что на входе и выходе функции ожидается одинаковый тип (string, number или любой другой).
const mathFunc = <T>(parameters: T): T => {
console.log(parameters);
return parameters
}
type SQRT = "SQRT";
type Multiplication = "multiplication";
const sqrt: SQRT = "SQRT";
const multiplication: Multiplication = "Multiplication";
mathFunc<SQRT>(sqrt);
const mathFunc = <T, U, R>(x: T, y: U): R => {
console.log("x + y = ", y);
return x + y;
};
type SQRT = "SQRT";
type Multiplication = "multiplication";
type Answer = "Answer";
const sqrt: SQRT = "SQRT";
const multiplication: Multiplication = "multiplication";
const answer: Answer = "Answer";
mathFunc<SQRT, Multiplication, Answer>(sqrt, multiplication);
const numberArray: Array<number> = [1, 2, 3, 4, 5];
const stringArray: Array<string> = ["one", "two", "three"];
function reverse<T>(array: T[]): T[] {
return array.reverse()
}
console.log(reverse(numberArray));
//[5, 4, 3, 2, 1]
console.log(reverse(stringArray));
//["three", "two", "one"]
Обобщённые типы в интерфейсах
interface IUser {
name: string,
age: number
}
interface IMessage {
id: number,
text: string
}
interface IState<T> {
loading: boolean,
error: Error | null,
data: T
}
type UserState = IState<IUser>;
type UserMessage = IState<IMessage>;
const messageState: UserMessage = {
loading: true,
error: null,
data: {
id: 1,
text: "33"
}
}
const n: number = 12;
const s: string = "string";
const user: IUser = {
name: "Yura",
age: 33
}
function identity<T> (arg: T) {
return arg;
}
const nn = identity(n);
const ss = identity(s);
const User = identity(user);
interface IAudi<AUDI> {
speed: AUDI;
testSpeed: () => AUDI;
}
const audi: IAudi = {};
//const audi: any
interface IAudiTT<AUDI = {}> {
speed: AUDI;
testSpeed: () => AUDI;
}
const audiTT: IAudiTT = {};
//const audiTT: IAudiTT<{}>
Обобщённые типы в классах
Встроенные дженерики
Array<T>
Внутренний тип, предоставляемый TypeScript. Array<number> идентичен записи number[]. В обоих случаях мы получаем массив чисел, отличие лишь в синтаксисе объявления типа.
const numberArray: Array<number> = [1, 2, 3, 4, 5];
const stringArray: Array<string> = ["one", "two", "three"];
function reverse<T>(array: T[]): T[] {
return array.reverse()
}
console.log(reverse(numberArray));
//[5, 4, 3, 2, 1]
console.log(reverse(stringArray));
//["three", "two", "one"]
ReadonlyArray<T>
Делаем массив доступным только для чтения.
const numberArray: ReadonlyArray<number> = [1, 2, 3, 4, 5];
const stringArray: Array<string> = ["one", "two", "three"];
function reverse<T>(array: T[]): T[] {
return array.reverse()
}
console.log(reverse(numberArray));
// The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.ts(2345)
console.log(reverse(stringArray));
//["three", "two", "one"]
Promise<T>
Он используется для указания возвращаемого типа в функциях async/await. Например, для типизации функции запроса к API.
const loadData = async (): Promise<TResponse> => await fetch('https://backend', ...)
Или если просто требуется создать промис:
const promise = new Promise<string>((resolve) => {
resolve("Всё просто, указана строка, резолвим строку")
});
Omit<T>
С его помощью можно опустить поля типа или интерфейса.
Допустим, у нас есть тип TBook, и мы хотим сделать из него тип TAuthor. Тогда при объявлении нового типа следует убрать поля title и pages. Для этого воспользуемся Omit:
type TMessage = {
readonly id: number,
readonly text: string,
read: () => string
}
type TText = Omit<TMessage, "text" | "read">
const text: TText = {
id: 123
}
Filed under: TypeScript - @ 09.01.2023 22:42