TypeScript — интерфейсы и объекты
Интерфейсы в TypeScript широко используются для определения формы объектов. Они позволяют задать структуру объекта, определяя какие свойства (и методы) он должен содержать, а также типы этих свойств.
Давайте более подробно рассмотрим интерфейсы для объектов на примерах:
interface Person {
name: string;
age: number;
}
let bob: Person = { name: "Bob", age: 30 }; // правильно
let alice: Person = { age: 25 }; // ошибка, отсутствует свойство 'name'
В этом примере интерфейс Person определяет, что объект должен иметь свойства name и age.
Необязательные Свойства
Интерфейсы могут включать необязательные свойства, что делает их идеальными для описания объектов, у которых могут отсутствовать некоторые свойства.
interface Employee {
name: string;
age: number;
position?: string; // необязательное свойство
}
let manager: Employee = { name: "Alice", age: 42, position: "Manager" };
let intern: Employee = { name: "Bob", age: 24 }; // Допустимо, так как 'position' необязательное
Read Only Свойства
Интерфейсы могут включать свойства только для чтения, которые нельзя изменить после их первоначальной инициализации.
interface Car {
readonly make: string;
readonly model: string;
year: number;
}
let myCar: Car = { make: "Toyota", model: "Corolla", year: 2015 };
myCar.year = 2020; // Допустимо
myCar.make = "Honda"; // Ошибка: нельзя изменить 'make', так как оно readonly
Интерфейсы с Индексируемыми Типами
Интерфейсы могут определять объекты, которые индексируются ключом определенного типа, например, строки или числа.
interface PhoneBook {
[name: string]: string;
}
let phones: PhoneBook = {};
phones["Alice"] = "123-4567";
phones["Bob"] = "987-6543";
[name: string]: string — это индексируемый тип.
Здесь name не является конкретным свойством, а скорее указателем на тип ключа (в данном случае string).
Таким образом, любой строковый ключ может быть использован для доступа к значению типа string в объекте, который соответствует этому интерфейсу.
Интерфейсы для Функций в Объектах
Можно определять интерфейсы, в которых одно или несколько свойств являются функциями.
interface MathOperations {
sum: (a: number, b: number) => number;
multiply: (a: number, b: number) => number;
}
- Внутри интерфейса MathOperations определены два свойства: sum и multiply. Оба эти свойства являются функциями.
- sum: (a: number, b: number) => number; — определяет функцию sum, которая принимает два параметра типа number (обозначенных как a и b) и возвращает значение типа number.
- multiply: (a: number, b: number) => number; — определяет функцию multiply, которая аналогично принимает два параметра типа number и возвращает значение типа number.
let operations: MathOperations = {
sum: (a, b) => a + b,
multiply: (a, b) => a * b,
};
- let operations: MathOperations — создается переменная operations, которая объявляется с типом MathOperations. Это означает, что объект operations должен соответствовать структуре, определенной интерфейсом MathOperations.
- В объекте operations определены две функции sum и multiply, соответствующие объявлениям в интерфейсе MathOperations.
- sum: (a, b) => a + b — реализация функции sum, которая складывает два числа.
- multiply: (a, b) => a * b — реализация функции multiply, которая умножает два числа.
let result = operations.multiply(2, 3); // результат: 6
- Здесь вызывается функция multiply объекта operations с аргументами 2 и 3.
- Функция multiply умножает эти числа, возвращая результат 6.
Расширение
Интерфейсы могут быть расширены другими интерфейсами, что позволяет комбинировать несколько интерфейсов в один.
interface BasicAddress {
street: string;
city: string;
}
interface AddressWithZip extends BasicAddress {
zipCode: number;
}
let address: AddressWithZip = { street: "123 Main St", city: "Anytown", zipCode: 12345 };