Sanyanggae LogoSanyanggae

📱 Tworzenie oprogramowania mobilnego i aplikacji

Typy warunkowe i infer w TypeScript: przekształcenia na małych przykładach

Przykłady typów warunkowych, dystrybucji unii i literałów szablonowych oraz różnica wobec walidacji w czasie działania.

사냥개 (Sanyanggae)Opublikowano Zaktualizowano 8 minut

To tłumaczenie koreańskiego oryginału. Koreański oryginał · Weryfikacja tłumaczenia: Weryfikacja przez SI

Typy warunkowe i infer w TypeScript: schemat typów warunkowych, infer i dystrybucji oraz kontroli w czasie działania
Schemat objaśniający Sanyanggae · Typy warunkowe · infer i dystrybucja · Kontrola wykonania.

Przy powtarzaniu podobnych deklaracji w TypeScript szuka się obliczania wyniku z typu wejściowego. Ważniejsza od liczby znaków jest czytelność relacji między typami. Fikcyjna usługa powiadomień o przesyłkach przedstawia typy warunkowe i infer, oddzielając je od sprawdzania rzeczywistej poprawności danych zewnętrznych.

1. Typ warunkowy jest rozgałęzieniem przyjmującym typ

Oficjalna dokumentacja opisuje wybór wyniku przez extends. Przykład tworzy logiczny typ literałowy zależnie od string. Nie jest funkcją sprawdzającą napisy podczas działania.

type IsText<T> = T extends string ? true : false;
type NameIsText = IsText<'parcel'>; // true
type CountIsText = IsText<3>;       // false

Załóżmy, że funkcja powiadomień przyjmuje identyfikator tekstowy, a wewnętrzna liczbowy. Przed typem warunkowym umiej wyjaśnić rozróżnienie. Inny sens uzasadnia osobne nazwy; sama notacja może być czytelniejsza po ujednoliceniu wejścia. Nie maskuj niejasnego projektu danych techniką typów.

Zapisuj oczekiwane wejścia i wyniki parami. Małe przykłady tekstu, liczb, unii i niespodziewanych wejść ułatwiają złożone deklaracje. Sprawdź zgodność komentarza i typu wnioskowanego przez edytor. Naturalna nazwa nie gwarantuje obliczonego wyniku.

2. Dystrybucja unii zmienia znaczenie tablicy

Gdy parametr typu stoi bezpośrednio po lewej warunku, warunek rozdziela się na członków unii. Aby traktować całość jako jednostkę, porównaj zapis w nawiasach kwadratowych.

type SeparateLists<T> = T extends unknown ? T[] : never;
type Together<T> = [T] extends [unknown] ? T[] : never;
type A = SeparateLists<string | number>; // string[] | number[]
type B = Together<string | number>;      // (string | number)[]
const a: A = ['a', 'b'];
const b: B = ['a', 1];

Pierwszy oznacza tablicę samych tekstów lub samych liczb. Drugi dopuszcza je razem. Wybór zależy od tego, czy cała lista ma zawierać jeden rodzaj kodów, czy różne rodzaje w elementach. Nawiasy wyglądają podobnie, kontrakty nie.

Przy błędach wkładaj członków osobno zamiast czytać od razu cały złożony utility. Porównaj tekst, liczbę i ich unię. Gdy widać zamierzoną dystrybucję, można uzasadnić nawiasy. W zapisie kontroli zachowuj przykłady dozwolonych wartości, nie tylko wynik.

3. infer nazywa typ wewnątrz struktury

infer nadaje nazwę części struktury dopasowanej w warunku. Mały przykład zdejmuje jedną warstwę Promise.

type OneResult<T> = T extends Promise<infer Value> ? Value : T;
type Parcel = OneResult<Promise<{ tracking: string }>>;
type ParcelList = OneResult<Promise<string[]>>;

Kod nie uruchamia asynchroniczności ani nie czeka, tylko wyraża kształt przy kompilacji. Nazwa Resolved może sugerować otrzymaną wartość: sprawdź kontekst. Oczekiwanie podczas działania nadal obsługuje kod asynchroniczny.

Jeśli potrzeba rekurencyjnie oczekiwanego wyniku, sprawdź standardowy Awaited przed rozbudową przykładu. Prostota nauki i wymagania wspólnego narzędzia są różne. Dokumentuj dla zespołu wejścia o innym wyniku niż standard oraz uzasadnienie różnicy.

4. Łączenie nazw zdarzeń literałami szablonowymi

Typy literałów szablonowych wyrażają kombinacje napisów. Usługa może połączyć obszar i działanie w nazwę zdarzenia.

type Scope = 'parcel' | 'address';
type Action = 'created' | 'updated';
type EventName = `${Scope}:${Action}`;
const event: EventName = 'parcel:created';

Kompilacja wykrywa literówki, ale nie dowodzi ważności każdej kombinacji w usłudze. Gdy obsługiwane jest tylko usuwanie adresu, iloczyn obszaru i działania może źle opisywać regułę. Najpierw rozważ jawne przyporządkowanie dozwolonych zdarzeń i payloadów.

Przy wielu zdarzeniach czytelnik musi łatwo znaleźć rzeczywiste nazwy. Zamiast wielopoziomowych reguł łączenia można trzymać nazwy dla systemów zewnętrznych w pliku. Porównaj, jak nowy członek wykryje błędne zdarzenie przed i po abstrakcji. Wyrafinowanie i użyteczność oceniaj razem.

5. Zewnętrzny JSON sprawdza się podczas działania

Typ User lub Parcel przy odpowiedzi API nie gwarantuje rzeczywistej struktury. Przyjmij jako unknown, potem sprawdź wymagane pola.

function hasTracking(value: unknown): value is { tracking: string } {
  return typeof value === 'object' && value !== null
    && 'tracking' in value && typeof value.tracking === 'string';
}
const incoming: unknown = { tracking: 'DEMO-001' };
if (hasTracking(incoming)) console.log(incoming.tracking);

Test potwierdza tylko tekst w tracking, nie istnienie numeru ani uprawnienie użytkownika do przesyłki. Zawężanie, reguły biznesowe i kontrola dostępu to różne odpowiedzialności. Dokumentacja Narrowing wyjaśnia zawężanie warunkami.

6. Mała kolejność wyboru narzędzi typów

Zapisz najpierw dwie realne wartości dopuszczone i dwie odrzucone. Wyraź sens zwykłą unią i jawnym obiektem. Gdy zostają powtarzane relacje, typ warunkowy i infer mają jasny powód. Jeżeli czytanie trwa znacznie dłużej, wydziel tylko wspólne części, resztę pozostaw zwykłą.

Oddzielnie wykonuj kontrolę typów i runtime. Odrzucenie złej nazwy przez kompilator i zrozumiały błąd przy brakujących polach serwera uzupełniają się. Po małych przykładach połącz kontrolę z rzeczywistą granicą wejścia, by przekształcenia pomagały bezpiecznie projektować aplikację.

Dowody i źródła

Artykuł wyjaśnia informacje ze źródeł publicznych. Cytowanie instytucji nie oznacza, że sprawdziła lub zatwierdziła tekst.

O wydawcy i kontakt

Inne artykuły na ten temat