Zaawansowane typy TypeScript wyjaśnione na przykładach
TypeScript oferuje kilka zaawansowanych typów wykraczających poza podstawowe typy, umożliwiając bardziej elastyczne i wydajne systemy typów. Te zaawansowane typy pomagają w tworzeniu solidnych aplikacji, zapewniając dodatkowe sposoby definiowania i egzekwowania ograniczeń typów. W tym artykule omówiono niektóre z tych zaawansowanych typów z przykładami.
Typy związków
Typy unii pozwalają zmiennej być jednym z kilku typów. Może to być przydatne, gdy wartość może być wielu typów, ale powinna być odpowiednio obsługiwana na podstawie jej rzeczywistego typu.
// Union type example
function formatValue(value: string | number): string {
if (typeof value === 'string') {
return `String: ${value}`;
} else {
return `Number: ${value.toFixed(2)}`;
}
}
console.log(formatValue("Hello"));
console.log(formatValue(123.456));
W tym przykładzie funkcja `formatValue` akceptuje ciąg znaków lub liczbę i odpowiednio formatuje wartość.
Typy skrzyżowań
Typy przecięcia łączą wiele typów w jeden. Obiekt typu przecięcia będzie miał wszystkie właściwości połączonych typów. Jest to przydatne do łączenia wielu typów.
// Intersection type example
interface Person {
name: string;
age: number;
}
interface Contact {
email: string;
phone: string;
}
type Employee = Person & Contact;
const employee: Employee = {
name: "John Doe",
age: 30,
email: "john.doe@example.com",
phone: "123-456-7890"
};
console.log(employee);
W tym przypadku typ „Pracownik” stanowi przecięcie „Osoby” i „Kontaktu”, co oznacza, że zawiera właściwości z obu interfejsów.
Typy dosłowne
Typy literałowe określają dokładne wartości, jakie zmienna może przechowywać. Może to być szczególnie przydatne do zapewnienia, że dozwolone są tylko pewne określone wartości.
// Literal type example
type Direction = "up" | "down" | "left" | "right";
function move(direction: Direction): void {
console.log(`Moving ${direction}`);
}
move("up"); // Valid
move("down"); // Valid
// move("side"); // Error: Argument of type '"side"' is not assignable to parameter of type 'Direction'.
Typ `Direction` jest tutaj ograniczony do czterech określonych wartości ciągu, co zapewnia, że w funkcji `move` można używać tylko tych kierunków.
Typy krotek
Typy krotek reprezentują tablicę ze stałą liczbą elementów, gdzie każdy element może mieć inny typ. Krotki są przydatne do reprezentowania kolekcji o stałym rozmiarze heterogenicznych elementów.
// Tuple type example
let user: [string, number] = ["Alice", 30];
console.log(user[0]); // "Alice"
console.log(user[1]); // 30
// user = [30, "Alice"]; // Error: Type 'number' is not assignable to type 'string'.
Krotka `user` jest zdefiniowana przy użyciu ciągu znaków, po którym następuje liczba, i ta struktura musi zostać zachowana.
Typy warunkowe
Typy warunkowe pozwalają na określenie typów na podstawie warunków. Zapewniają sposób na wybranie jednego lub drugiego typu na podstawie warunku.
// Conditional type example
type IsString = T extends string ? "Yes" : "No";
type Test1 = IsString; // "Yes"
type Test2 = IsString; // "No"
W tym przykładzie typ `IsString` sprawdza, czy typ `T` jest ciągiem znaków. Zwraca `"Yes"`, jeśli tak jest, a `"No"` w przeciwnym wypadku.
Typy mapowane
Mapowane typy umożliwiają tworzenie nowych typów poprzez transformację właściwości istniejącego typu. Jest to przydatne do modyfikowania lub rozszerzania istniejących typów.
// Mapped type example
type ReadonlyPerson = {
readonly [K in keyof Person]: Person[K];
};
const readonlyPerson: ReadonlyPerson = {
name: "Alice",
age: 30
};
// readonlyPerson.age = 31; // Error: Cannot assign to 'age' because it is a read-only property.
Typ `ReadonlyPerson` przekształca typ `Person`, sprawiając, że wszystkie jego właściwości stają się tylko do odczytu.
Wniosek
Zaawansowane typy TypeScript zapewniają potężne narzędzia do definiowania i zarządzania złożonymi wymaganiami dotyczącymi typów. Wykorzystując typy union, intersection, literal, tuple, conditional i mapped, programiści mogą tworzyć bardziej solidne i łatwiejsze w utrzymaniu aplikacje. Zrozumienie i skuteczne stosowanie tych typów może znacznie zwiększyć bezpieczeństwo typów i elastyczność kodu TypeScript.