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: "[email protected]",
  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.