5.1 Оператор keyof
Кроме всего прочего, в TypeScript есть еще один интересный оператор — keyof. Он позволяет создавать типы, основанные на ключах другого типа. Сейчас вы узнаете о нем кое-что интересное.
Оператор keyof в TypeScript используется для получения типа, представляющего ключи другого типа. Этот оператор возвращает тип, представляющий набор всех ключей переданного типа в виде объединения строковых литералов.
Синтаксис:
type Keys = keyof Type;
Пример использования:
interface Person {
name: string;
age: number;
address: string;
}
type PersonKeys = keyof Person; // 'name' | 'age' | 'address'
let key: PersonKeys;
key = "name"; // Допустимо
key = "age"; // Допустимо
key = "address"; // Допустимо
// key = "phone"; // Ошибка: Type '"phone"' is not assignable to type 'PersonKeys'.
Здесь тип PersonKeys — объединение строковых литералов 'name', 'age' и 'address', которые являются ключами интерфейса Person.
5.2 Типы индексирования
Типы индексирования в TypeScript позволяют использовать значения в качестве ключей типов. Они особенно полезны при работе с объектами и дают возможность создавать более гибкие и универсальные типы.
Синтаксис:
type IndexedType = Type[Key];
Здесь:
тype— это тип объектаKey— это тип ключа- тип
IndexedTypeбудет типом значения, связанного с ключомKeyв объектеType
Пример использования
interface Person {
name: string;
age: number;
address: string;
}
type NameType = Person["name"]; // string
type AgeType = Person["age"]; // number
type AddressType = Person["address"]; // string
Здесь тип NameType будет string, AgeType — number, а AddressType — string.
5.3 Комбинирование keyof и типов индексирования
Комбинирование оператора keyof и типов индексирования позволяет создавать более сложные и типобезопасные структуры. Например, можно создавать функции, которые работают с объектами и их ключами, обеспечивая при этом типовую безопасность.
Пример использования:
"use strict";
function getProperty(obj, key) {
return obj[key];
}
const person = {
name: "Alice",
age: 30,
address: "123 Main St"
};
// Пример использования функции с типовой безопасностью
let name = getProperty(person, "name"); // string
let age = getProperty(person, "age"); // number
let address = getProperty(person, "address"); // string
// let invalid = getProperty(person, "phone"); // Ошибка: Argument of type '"phone"' is not assignable to parameter of type 'keyof Person'.
console.log(name); // Вывод: Alice
console.log(age); // Вывод: 30
console.log(address); // Вывод: 123 Main St
interface Person {
name: string;
age: number;
address: string;
}
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const person: Person = {
name: "Alice",
age: 30,
address: "123 Main St"
};
// Пример использования функции с типовой безопасностью
let name = getProperty(person, "name"); // string
let age = getProperty(person, "age"); // number
let address = getProperty(person, "address"); // string
// let invalid = getProperty(person, "phone"); // Ошибка: Argument of type '"phone"' is not assignable to parameter of type 'keyof Person'.
console.log(name); // Вывод: Alice
console.log(age); // Вывод: 30
console.log(address); // Вывод: 123 Main St
Здесь функция getProperty принимает объект obj типа T и ключ key типа K, который должен быть одним из ключей объекта T. Это обеспечивает типовую безопасность, гарантируя, что ключ существует в объекте.
5.4 Примеры использования на практике
Обновление свойств объекта
Использование оператора keyof и типов индексирования позволяет создавать функции для обновления свойств объекта с типовой безопасностью:
"use strict";
function updateProperty(obj, key, value) {
obj[key] = value;
}
let user = {
name: "Bob",
age: 25,
address: "456 Elm St"
};
updateProperty(user, "name", "Robert");
updateProperty(user, "age", 26);
// updateProperty(user, "phone", "123-456-7890"); // Ошибка: Argument of type '"phone"' is not assignable to parameter of type 'keyof Person'.
console.log(user); // { name: 'Robert', age: 26, address: '456 Elm St' }
function updateProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
obj[key] = value;
}
interface Person {
name: string;
age: number;
address: string;
}
let user: Person = {
name: "Bob",
age: 25,
address: "456 Elm St"
};
updateProperty(user, "name", "Robert");
updateProperty(user, "age", 26);
// updateProperty(user, "phone", "123-456-7890"); // Ошибка: Argument of type '"phone"' is not assignable to parameter of type 'keyof Person'.
console.log(user); // { name: 'Robert', age: 26, address: '456 Elm St' }
Создание динамических типов
Комбинирование keyof и типов индексирования позволяет создавать динамические типы, которые адаптируются к структуре других типов:
"use strict";
let personProps = {
name: "Charlie",
age: 28,
address: "789 Oak St"
};
console.log(personProps); // { name: 'Charlie', age: 28, address: '789 Oak St' }
interface Person {
name: string;
age: number;
address: string;
}
type PersonProperties = {
[K in keyof Person]: Person[K];
};
let personProps: PersonProperties = {
name: "Charlie",
age: 28,
address: "789 Oak St"
};
console.log(personProps); // { name: 'Charlie', age: 28, address: '789 Oak St' }
5.5 Сильные стороны keyof и типов индексирования
Преимущества использования keyof и типов индексирования
- Типобезопасность: оператор
keyofи типы индексирования позволяют создавать типобезопасные API и абстракции, что помогает предотвратить ошибки на этапе компиляции. - Гибкость: эти инструменты позволяют создавать универсальные и динамические типы, которые адаптируются к структуре других типов.
- Повторное использование кода: комбинирование
keyofи типов индексирования позволяет создавать обобщенные функции и классы, которые можно использовать в различных контекстах. - Улучшенная читаемость и поддерживаемость: использование этих инструментов делает код более понятным и легко поддерживаемым, так как они четко определяют структуру данных и их изменения.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ