KeyOf i Typeof w TypeScript

TypeScript

readTime

5 min

KeyOf i Typeof w TypeScript

W tym wpisie omówię keyof, typeof, mapped types, conditional types i dowiesz się, jak używać ich w codziennej pracy.

Wprowadzenie do Typów w TypeScript

TypeScript (TS) to nadzbiór JavaScriptu, który dodaje statyczne typowanie do języka.

Dzięki temu możesz typować swoje zmienne, funkcje i obiekty, co pomaga wykrywać błędy już na etapie kompilacji.

Ale TypeScript to nie tylko podstawowe typy jak stringi czy number. Pozwala też na zaawansowane techniki typowania, takie jak keyof, typeof, mapped types i conditional types.

Zrozumienie Keyof w TypeScript

Co to jest Keyof?

Słowo kluczowe keyof to operator w TypeScripcie, który zwraca unię łańcuchów reprezentujących nazwy wszystkich kluczy danego typu obiektowego.

Jak Używać Keyof?

Załóżmy, że masz interfejs:

typescript
interface User {
  id: number;
  name: string;
  email: string;
}

Kiedy użyjesz keyof User, otrzymasz typ równoważny 'id' | 'name' | 'email'.

Przykład z Keyof

typescript
type UserKeys = keyof User; // 'id' | 'name' | 'email'

let key: UserKeys;

key = "name"; // OK
key = "address"; // Błąd: Type '"address"' is not assignable to type 'UserKeys'

Dzięki keyof możesz tworzyć bardziej zaawansowane typy, które gwarantują, że używasz tylko dostępnych kluczy obiektu.

Co to jest Typeof w JavaScript?

W JavaScripcie mamy operator typeof, który zwraca typ zmiennej w postaci łańcucha znaków, np. 'string', 'number'.

W TypeScripcie operator typeof może być użyty w kontekście typowania, aby odczytać typ danej zmiennej lub obiektu.

Jak Używać Typeof w TypeScript?

Jeśli masz zmienną:

typescript
let user = {
  id: 1,
  name: "Alice",
  email: "alice@example.com",
};

Możesz utworzyć typ bazujący na typie tej zmiennej:

typescript
type UserType = typeof user;

Teraz UserType ma dokładnie ten sam typ, co user.

Przykład z Typeof

typescript
function getUser(): UserType {
  return {
    id: 2,
    name: "Bob",
    email: "bob@example.com",
  };
}

Typeof pozwala przypisać typ istniejącej zmiennej do nowego typu.

Co to są Mapped Types w TypeScript?

Mapped types to typy, które pozwalają na mapowanie jednego typu na inny, przekształcając jego właściwości.

Użycie Mapped Types: Partial, Required, Readonly, Pick, Omit

TypeScript dostarcza kilka wbudowanych utility types, które są mapped types:

  • Partial<T>: Ustawia wszystkie właściwości typu T jako opcjonalne.
  • Required<T>: Ustawia wszystkie właściwości typu T jako wymagane.
  • Readonly<T>: Ustawia wszystkie właściwości typu T jako tylko do odczytu.
  • Pick<T, K>: Tworzy typ z podzbioru właściwości K z typu T.
  • Omit<T, K>: Tworzy typ z właściwości typu T bez właściwości K.

Przykładowy Mapped Type

Partial

typescript
type PartialUser = Partial<User>;

// Wszystkie właściwości są opcjonalne
let user1: PartialUser = { name: "Charlie" };

Required

typescript
type RequiredUser = Required<User>;

// Wszystkie właściwości są wymagane
let user2: RequiredUser = {
  id: 3,
  name: "Dana",
  email: "dana@example.com",
};

Pick

typescript
type UserNameAndEmail = Pick<User, "name" | "email">;

// Typ z tylko 'name' i 'email'
let user3: UserNameAndEmail = {
  name: "Eve",
  email: "eve@example.com",
};

Omit

typescript
type UserWithoutEmail = Omit<User, "email">;

// Typ z wszystkimi właściwościami poza 'email'
let user4: UserWithoutEmail = {
  id: 4,
  name: "Frank",
};

Tworzenie Własnych Mapped Types

Możesz też tworzyć własne mapped types:

typescript
type MyMappedType<T> = {
  [P in keyof T]: string;
};

// Wszystkie właściwości typu T będą typu string
type StringifiedUser = MyMappedType<User>;

let user5: StringifiedUser = {
  id: "5",
  name: "Grace",
  email: "grace@example.com",
};

Zaawansowane Typowanie z Conditional Types

Zrozumienie Conditional Types

Conditional types pozwalają na tworzenie typów, które zależą od pewnych warunków.

Składnia jest podobna do operatora trójargumentowego w JavaScript:

typescript
T extends U ? X : Y

Jeśli T jest podtypem U, to wynikiem jest X, w przeciwnym razie Y.

Przykład z Conditional Types

typescript
type IsString<T> = T extends string ? true : false;

type A = IsString<string>; // true
type B = IsString<number>; // false

Zastosowania Conditional Types

Conditional types są bardzo przydatne w kontekście tworzenia typów generycznych, które mogą się zmieniać w zależności od przekazanych parametrów.

Łączenie Keyof, Typeof i Mapped Types

Tworzenie Typu na Podstawie Kluczy Obiektu

typescript
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

let user6 = { id: 6, name: "Hank", email: "hank@example.com" };

let userName = getProperty(user6, "name"); // Typ string

Tutaj użyliśmy keyof do ograniczenia klucza K do istniejących kluczy obiektu T.

Użycie Typeof z Keyof

typescript
const COLORS = {
  red: "#FF0000",
  green: "#00FF00",
  blue: "#0000FF",
};

type ColorKeys = keyof typeof COLORS; // 'red' | 'green' | 'blue'

Typeof pozwala nam utworzyć typ na podstawie COLORS, a keyof wyciąga klucze tego typu.

Podsumowanie

Poznanie keyof i typeof w TypeScript otwiera drzwi do bardziej zaawansowanych technik typowania.

Mapped types, takie jak Partial, Required, Pick, czy Omit, ułatwiają manipulowanie typami i tworzenie bardziej elastycznego kodu.

Conditional types dodają kolejny poziom dynamiki, pozwalając na typowanie zależne od warunków.

Mam nadzieję, że ten artykuł pomógł Ci zrozumieć te potężne narzędzia w TypeScript. Zachęcam do eksperymentowania i programowania własnych rozwiązań. Jeśli masz pytania lub chcesz podzielić się swoimi doświadczeniami, zostaw komentarz!

authorImg

Witek Pruchnicki

Z pasją dzielę się wiedzą o programowaniu i nie tylko na różne sposoby

TypeScript

Więcej