Утилитарные типы в TypeScript
В этой статье объясняются утилитарные типы в TypeScript.
YouTube Video
Утилитарные типы в TypeScript
Утилитарные типы TypeScript - это удобные инструменты для создания новых типов на основе существующих типов. Это позволяет создавать более гибкие определения типов и увеличивает переиспользование кода. Здесь мы подробно объясним часто используемые утилитарные типы и обсудим, как использовать каждый из них с примерами кода.
Partial<T>
Partial<T> делает все свойства типа объекта необязательными (позволяя использовать undefined). Это полезно, когда вы хотите использовать только некоторые из свойств исходного типа.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7function updateUser(user: Partial<User>) {
8 console.log(user);
9}
10
11updateUser({ name: "Alice" }); // Updates only 'name'
- В приведенном выше примере использование
Partial<User>делает все свойства типаUserнеобязательными. Таким образом, в функцииupdateUserвы можете передать только подмножество свойств.
Required<T>
Required<T> делает все свойства, включая необязательные, обязательными. Он используется, когда вы хотите преобразовать необязательные свойства в обязательные.
1interface User {
2 id: number;
3 name?: string;
4 age?: number;
5}
6
7function createUser(user: Required<User>) {
8 console.log(user);
9}
10
11// createUser({ id: 1 }); // Error: 'name' and 'age' are required
12createUser({ id: 1, name: "Alice", age: 25 });- Используя
Required<User>, такие свойства, какnameиage, считаются обязательными.
Readonly<T>
Readonly<T> делает все свойства объекта доступными только для чтения. Это предотвращает изменение значений объекта.
1interface User {
2 id: number;
3 name: string;
4}
5
6const user: Readonly<User> = {
7 id: 1,
8 name: "Alice"
9};
10
11// user.id = 2; // Error: 'id' is read-only
12console.log(user);- Используя
Readonly<T>, вы можете защитить свойства объекта от изменения. Это эффективно, когда вы хотите предотвратить случайное изменение данных во время разработки.
Record<K, T>
Record<K, T> создает тип карты со специфицированными типами ключей и значений. K - это тип ключей (например, string или number), а T - это тип значений.
1type Roles = "admin" | "user" | "guest";
2interface ReadWritePermissions {
3 read: boolean;
4 write: boolean;
5}
6
7const rolePermissions: Record<Roles, ReadWritePermissions> = {
8 admin: { read: true, write: true },
9 user: { read: true, write: false },
10 guest: { read: false, write: false },
11};
12
13console.log(rolePermissions);Record<K, T>полезен, когда вы хотите определить пары ключ-значение. В приведенном выше примере разрешения определяются на основе ролей пользователей.
Pick<T, K>
Pick<T, K> извлекает только указанные свойства из типа объекта. Вы можете создать новый тип, извлекая только необходимые свойства.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5}
6
7type UserSummary = Pick<User, "id" | "name">;
8
9const summary: UserSummary = {
10 id: 1,
11 name: "Alice"
12};
13
14console.log(summary);- Используя
Pick<T, K>, вы можете извлечь определенные свойства из типа объекта и рассматривать их как новый тип. Например, в приведенном выше примере извлекаются толькоidиname.
Omit<T, K>
Omit<T, K> исключает указанные свойства из типа объекта. Это противоположная операция Pick.
1interface User {
2 id: number;
3 name: string;
4 age: number;
5 email: string;
6}
7
8type UserWithoutEmail = Omit<User, "email">;
9
10const userWithoutEmail: UserWithoutEmail = {
11 id: 1,
12 name: "Alice",
13 age: 25
14};
15
16console.log(userWithoutEmail);- Используя
Omit<T, K>, вы можете создать новый тип, исключив указанные свойства. В приведённом выше примере свойствоemailисключено.
Exclude<T, U>
Exclude<T, U> создаёт новый тип, удаляя тип U из объединённого типа T. Это используется, когда нужно удалить определённый тип.
1type Status = "active" | "inactive" | "pending";
2type ExcludedStatus = Exclude<Status, "pending">;
3
4const userStatus: ExcludedStatus = "active"; // "pending" is excluded, so it cannot be chosen
5console.log(userStatus);- С помощью
Exclude<T, U>вы можете удалить ненужные типы из объединённого типа. В приведённом выше примере, поскольку"pending"исключён, можно выбрать только"active"или"inactive".
Extract<T, U>
Extract<T, U> извлекает части, соответствующие типу U внутри объединённого типа T. Это полезно, когда нужно извлечь только определённый тип.
1type Status = "active" | "inactive" | "pending";
2type ActiveStatus = Extract<Status, "active" | "pending">;
3
4const userStatus: ActiveStatus = "active"; // "inactive" cannot be chosen
5console.log(userStatus);Extract<T, U>выполняет противоположную операциюExclude. В приведённом выше примере можно выбрать только"active"и"pending".
NonNullable<T>
NonNullable<T> создаёт тип, исключая null и undefined. Это полезно, когда нужно исключить эти значения из необязательных типов.
1type UserName = string | null | undefined;
2type ValidUserName = NonNullable<UserName>;
3
4const userName: ValidUserName = "Alice"; // null and undefined cannot be chosen
5console.log(userName);NonNullable<T>исключает значенияnullиundefined, гарантируя, что значение присутствует.
Заключение
Утилитарные типы TypeScript — это мощные инструменты для создания более лаконичных и гибких определений типов. Понимание и правильное использование основных утилитарных типов, таких как Partial, Required, Readonly, Record и других, может улучшить переиспользуемость и удобство сопровождения кода. Освоение этих типов позволяет создавать более надёжные и безопасные определения типов, что способствует эффективной разработке.
Оператор keyof в TypeScript
Оператор keyof в TypeScript используется для получения всех имён свойств типа объекта. Используя этот оператор, вы можете получить ключи типа объекта как объединенный тип. Это чрезвычайно полезно для написания кода с безопасными типами.
Основное использование
1interface Person {
2 name: string;
3 age: number;
4 email: string;
5}
6
7// Use keyof to get the property names of Person
8type PersonKeys = keyof Person; // "name" | "age" | "email"
Пример использования
Использование в аргументах функции
Вы можете использовать keyof для определения функции, которая имеет типы, основанные на конкретных свойствах объекта.
1function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
2 return obj[key];
3}
4
5const person: Person = { name: "Alice", age: 30, email: "alice@example.com" };
6const userName = getProperty(person, "name"); // type is string
7const age = getProperty(person, "age"); // type is number
8
9console.log("Name:", userName);
10console.log("Age:", age);- Эта функция получает свойство из объекта безопасным с точки зрения типов способом на основе указанного ключа.
Улучшение ограничений типов
Используя keyof, вы можете гарантировать, что ключи, передаваемые в функцию, проверяются на этапе компиляции.
1// Passing an invalid property name results in an error
2const invalid = getProperty(person, "invalidKey"); // Error
- Этот код демонстрирует, что указание несуществующего имени свойства приведет к ошибке компиляции.
Резюме
- Оператор
keyofиспользуется для получения всех имен свойств типа объекта. - Вы можете получить имена свойств как объединенный тип, что обеспечивает безопасность типов в коде.
- Используя его в аргументах функции, вы можете ограничить функцию только допустимыми именами свойств.
Таким образом, оператор keyof повышает безопасность типов в TypeScript и помогает писать более надежный код.
Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.