Dalej poznajemy TypeScript i jego system typowania. W tym odcinku nieco o operatorach keyof, typeof oraz indeksach w kontekście typów. Zaczynajmy.

Ok, najpierw taki przykład:

type Person = { age: number; name: string; alive: boolean };
type Age = Person["age"];

Ta składnia oznacza, że typ Age ma mieć typ, jaki person ma pod kluczem age (czyli number).

Ok, kolejny przykład:

type I1 = Person["age" | "name"];

Tu mamy powiedziane, że typ I1 ma mieć unię typów, jakie pod person są pod kluczami age i name (czyli number | string).

Kolejny przykład:

type I2 = Person[keyof Person];

Tutaj domagamy się unii typów, jakie są typami wszystkich kluczy typu Person. Ok, jeszcze jeden przykład z dokumentacji:

type AliveOrName = "alive" | "name";
type I3 = Person[AliveOrName];

Tutaj mamy pokazane jak możemy uniknąć przydługich tekstów w kodzie. Zrobiliśmy sobie AliveOrName i tam trzymamy te klucze. Poniżej sprawdzamy, jakie typy pod tymi kluczami występują w Person i unię tych typów dopisujemy do I3.

Fajne jest też to, że możemy wyciągnąć typ z tablicy:

const MyArray = [
  { name: "Alice", age: 15 },
  { name: "Bob", age: 23 },
  { name: "Eve", age: 38 },
];
 
type Person = typeof MyArray[number];

Skutkuje to takim typem:

type Person = {
    name: string;
    age: number;
}

W zasadzie możemy dobrać się do age teraz tego na kilka sposobów:

type Age = typeof MyArray[number]["age"];
//type Age = number

//or

type Age2 = Person["age"];
//type Age2 = number

Ok, fajnie, zobaczmy operator keyof w akcji i pomyślmy, czy wszystko rozumiemy:

type Pt = { x: number; y: number };

type P = keyof Pt;
//'x' | 'y'

Teraz operator typeof:

let someVariable = 42;

type someVarVal = typeof someVariable;

//type someVarVal = number

To swoją drogą fajne, bo mamy tutaj dynamiczny typ, który zależy od jakiejś zmiennej.

Ok, zróbmy sobie taki obiekt:

const user = {
    name: 'John',
    age: 32
  };

Teraz zrobimy coś głupiego, aby pokazać, czego nie robić:

const user = {
    name: 'John',
    age: 32
  };

type Error = keyof user //error! user to object!

Nie wolno robić keyof na obiekcie! Tylko na typie wolno. Teraz postarajmy się ogarnąć, co możemy zrobić z tymi operatorami:

const user = {
    name: 'John',
    age: 32
  };

type UserType = typeof user;

// type UserType = {
//     name: string;
//     age: number;
// }

Typeof wyłuskał nam definicję typu z obiektu user (swoją drogą ucz się JSa mówili… jakbym się wskaźników uczył, „prostota” języków typu JS jest mocno umowna) i taki typ zapisał pod UserType.

Ok, ale keyof nie możemy użyć na obiekcie, tylko na typie, tak? Ale możemy połączyć operatory:

const user = {
    name: 'John',
    age: 32
  };

type UserKeys = keyof typeof user; // 'name' | 'age'

I mamy co chcieliśmy, typeof wyłuskał definicję typu z obiektu user, keyof wyłuskał z tego typu klucze i jako unię literal type zapisał pod typem UserKeys.

Na dzisiaj miałem przygotowane więcej ciekawych przykładów, ale myślę, że rozbijemy to sobie na kilka lekcji, nie chcę tutaj czytelnika przytłoczyć. Do następnego razu!