0Pricing
TypeScript Academy · Lekcja

Bezpieczeństwo typów interpolacji

Wyodrębniaj zmienne interpolacji ze stringów i wymagaj ich

Bezpieczeństwo typów interpolacji to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 4 lekcji w sumie.

Interpolacja bezpieczna typowo

Komunikaty często zawierają symbole zastępcze, takie jak "Hello, {name}". Bezpieczne typowo i18n wyodrębnia nazwy tych symboli z typu tekstu komunikatu i wymaga przekazania pasujących argumentów.

Cel

Mając typ literałowy komunikatu, chcemy obliczyć obiekt zmiennych, których on potrzebuje, aby wymusić użycie t("greet", { name: "Ada" }) i zgłosić brak name jako błąd kompilacji.

Wyodrębnianie jednego symbolu zastępczego

Warunkowy typ literału szablonowego wyciąga nazwę zmiennej z tekstu zawierającego pojedynczy symbol zastępczy. W prawdziwym kodzie wzorzec zapisuje się z użyciem backticków jako: ciąg znaków, klamra otwierająca, infer V, klamra zamykająca, ciąg znaków. Poniżej oznaczamy ten dopasowujący wzorzec jako BraceMatch.

// Real TS pattern (backtick template literal):
//   matches any text, then {V}, then any text; infers V.

type Var<S extends string> =
  S extends BraceMatch<infer V> ? V : never;

type A = Var<"Hello, {name}">; // "name"

Wyodrębnianie wielu symboli zastępczych

Należy użyć rekurencji, aby zebrać wszystkie symbole zastępcze w unię. Wzorzec przechwytuje jedną zmienną oraz pozostały fragment, a następnie uruchamia rekurencję dla tego fragmentu.

// Pattern: any text, {V}, then Rest tail -- infer V and Rest.

type Vars<S extends string> =
  S extends BraceMatchRest<infer V, infer Rest>
    ? V | Vars<Rest>
    : never;

type B = Vars<"Hi {first} {last}!">; // "first" | "last"

Od nazw do obiektu argumentów

Należy przekształcić unię nazw w wymagany typ obiektu za pomocą typu mapowanego.

type ArgsOf<S extends string> = {
  [K in Vars<S>]: string | number;
};

type G = ArgsOf<"Hello, {name}">;
// { name: string | number }

Brak symboli zastępczych, brak argumentów

Gdy komunikat nie zawiera symboli zastępczych, Vars ma wartość never, więc obiekt argumentów jest pusty. W takim przypadku można uczynić parametr argumentów opcjonalnym.

type C = Vars<"Goodbye">;       // never
type D = ArgsOf<"Goodbye">;     // {} (empty)

Typowana funkcja tłumacząca

Parametr argumentów powinien zależeć od wybranego klucza. W tym celu należy odszukać literał komunikatu i obliczyć jego argumenty.

declare const messages: {
  greet: "Hello, {name}";
  invite: "Join {count} others";
};

declare function t<K extends keyof typeof messages>(
  key: K,
  args: ArgsOf<(typeof messages)[K]>
): string;

Wymuszanie w praktyce

Kompilator wymaga teraz dokładnie tych zmiennych, które deklaruje każdy komunikat.

t("greet", { name: "Ada" });   // ok
t("greet", {});                 // Error: name is missing
t("invite", { count: 3 });      // ok
t("invite", { name: "x" });     // Error: count missing, name unexpected

Opcjonalne argumenty dla zwykłych komunikatów

Należy użyć przeciążenia warunkowego, aby komunikaty bez symboli zastępczych w ogóle nie wymagały drugiego argumentu.

type MaybeArgs<S extends string> =
  Vars<S> extends never ? [] : [args: ArgsOf<S>];

declare function t2<K extends keyof typeof messages>(
  key: K,
  ...rest: MaybeArgs<(typeof messages)[K]>
): string;

Własne ograniczniki

Jeśli katalog używa {{name}} lub %{name}, należy odpowiednio zmodyfikować wzorzec literału szablonowego w Vars. Technika pozostaje taka sama — zmienia się tylko otaczający literał.

Dlaczego to ma znaczenie

Brakujące lub błędnie wpisane zmienne interpolacji są częstą przyczyną uszkodzonych tekstów interfejsu ("Hello, undefined"). Wyodrębnienie ich na poziomie typów zamienia takie problemy w błędy kompilacji i dokumentuje kontrakt każdego komunikatu.

Szybki test

Proszę sprawdzić, czy rozumieją Państwo bezpieczeństwo typów interpolacji.

Podsumowanie

Dopasowując wzorce do typów literałów komunikatów za pomocą literałów szablonowych i infer, można wyodrębnić nazwy placeholderów do unii, przypisać je do wymaganego obiektu args oraz sprawić, że funkcja translate będzie wymagać dokładnie tych zmiennych, a gdy nie ma żadnych — otrzyma opcjonalny argument.

Często zadawane pytania

Czy lekcja „Bezpieczeństwo typów interpolacji” jest bezpłatna?

Tak — pełny tekst „Bezpieczeństwo typów interpolacji” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Bezpieczeństwo typów interpolacji”?

Wyodrębniaj zmienne interpolacji ze stringów i wymagaj ich Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?

Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Bezpieczeństwo typów interpolacji”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?

Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Typowanie kluczy tłumaczeń
  2. Bezpieczeństwo typów interpolacji
  3. Liczba mnoga z typami
  4. Wnioskowanie typów zależne od lokalizacji
← Powrót do TypeScript Academy