W programowaniu obiektowym, jednym z głównych sposobów organizacji kodu jest strukturalne definiowanie obiektów i ich właściwości. W TypeScript ten proces odbywa się za pomocą interfejsów. Interfejsy pozwalają na precyzyjne definiowanie kształtu obiektów i zapewniają, że wszystkie obiekty używane w kodzie spełniają określone wymagania. W tej części dowiemy się, jak definiować interfejsy oraz jak z nich korzystać.
Czym jest interfejs?
Interfejs to swego rodzaju kontrakt, który mówi, jakie właściwości i metody powinien mieć dany obiekt. Dzięki interfejsom możemy definiować strukturę danych bez bezpośredniej implementacji logiki. Interfejsy są szczególnie przydatne, gdy chcemy zdefiniować złożone obiekty lub upewnić się, że różne części kodu działają na spójnych danych.
Definiowanie prostego interfejsu
Aby stworzyć interfejs w TypeScript, używamy słowa kluczowego interface, a następnie określamy właściwości i ich typy. Oto prosty przykład:
interface Person {
name: string;
age: number;
}
W powyższym przykładzie zdefiniowaliśmy interfejs Person, który określa, że każdy obiekt tego typu musi mieć dwie właściwości:
name typu string.
age typu number.
Używanie interfejsu
Po zdefiniowaniu interfejsu możemy go użyć do typowania zmiennych, funkcji lub klas. Dzięki temu TypeScript będzie pilnował, aby każda instancja obiektu była zgodna z interfejsem.
Przykład:
let user: Person = {
name: "Jan Kowalski",
age: 30
};
Jeśli spróbujemy przypisać obiekt, który nie spełnia wymagań interfejsu, TypeScript zgłosi błąd:
let invalidUser: Person = {
name: "Anna",
// Brakuje właściwości 'age'
}; // Błąd! Brak właściwości 'age'
Właściwości opcjonalne
Czasami nie wszystkie właściwości obiektu muszą być obowiązkowe. W takim przypadku możemy oznaczyć właściwości jako opcjonalne za pomocą ?.
Przykład:
interface Car {
model: string;
year?: number; // Opcjonalna właściwość
}
let myCar: Car = {
model: "Toyota"
};
let anotherCar: Car = {
model: "Honda",
year: 2015
};
Właściwość year w interfejsie Car jest opcjonalna, więc obiekt może ją mieć, ale nie musi.
Funkcje w interfejsach
Interfejsy mogą również definiować metody, czyli funkcje, które będą częścią obiektu. Możemy określić typ parametrów oraz typ zwracany funkcji.
Przykład:
interface Person {
name: string;
age: number;
greet(): string; // Definicja funkcji w interfejsie
}
let user: Person = {
name: "Jan Kowalski",
age: 30,
greet(): string {
return `Cześć, jestem ${this.name}`;
}
};
console.log(user.greet()); // Cześć, jestem Jan Kowalski
Funkcja greet() została zdefiniowana w interfejsie Person i każda implementacja tego interfejsu musi dostarczyć tę funkcję.
Rozszerzanie interfejsów
Interfejsy mogą być rozszerzane, co pozwala na ich łączenie i tworzenie bardziej złożonych struktur. Jest to szczególnie przydatne, gdy chcemy budować bardziej zaawansowane struktury danych na bazie prostszych elementów.
W tym przypadku interfejs Manager rozszerza zarówno interfejs Person, jak i Employee, co oznacza, że obiekt typu Manager musi spełniać wymagania obu interfejsów.
Typy indeksowane
Interfejsy mogą również definiować typy indeksowane, co oznacza, że możemy dynamicznie definiować klucze obiektów.
W tym przykładzie interfejs StringDictionary pozwala na tworzenie obiektów, gdzie klucze są typu string, a wartości również są typu string.
Interfejsy w funkcjach
Interfejsy mogą również być używane do definiowania typów parametrów funkcji, co sprawia, że funkcje mogą przyjmować tylko obiekty zgodne z danym interfejsem.
Przykład:
function printPersonDetails(person: Person): void {
console.log(`Imię: ${person.name}, Wiek: ${person.age}`);
}
let user: Person = { name: "Jan", age: 30 };
printPersonDetails(user); // Imię: Jan, Wiek: 30
Funkcja printPersonDetails akceptuje tylko obiekty typu Person, co zapewnia, że zawsze otrzyma obiekt zgodny z interfejsem.
Podsumowanie
Interfejsy w TypeScript są niezwykle potężnym narzędziem, które pozwala na precyzyjne definiowanie kształtu obiektów, co sprawia, że kod staje się bardziej spójny i łatwiejszy w utrzymaniu. Kluczowe elementy interfejsów to:
Definiowanie właściwości i metod.
Właściwości opcjonalne.
Rozszerzanie interfejsów.
Używanie interfejsów w funkcjach i do typowania zmiennych.