0Pricing
React Academy · Lekcja

Rozłączne sumy dla wariantów komponentów

Modelowanie propsów wariantów za pomocą rozłącznych sum, aby TypeScript wymuszał prawidłowe kombinacje propsów.

Rozłączne sumy dla wariantów komponentów to bezpłatna lekcja React Academy na CoddyKit. To lekcja 1 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 React Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs React Academy zawiera 4 lekcji w sumie.

Problem z propsami wariantów

Komponent z opcjonalnymi propsami dla różnych trybów (np. przycisk, który jest linkiem albo przyciskiem) może dopuszczać nieprawidłowe kombinacje propsów. TypeScript nie wykryje ich bez unii rozłącznych.

Czym jest unia rozłączna

Unia rozłączna to unia typów, które współdzielą wspólne pole typu literałowego (dyskryminant). TypeScript zawęża typ na podstawie wartości tego pola.

type Shape =
  | { kind: 'circle'; radius: number }
  | { kind: 'rectangle'; width: number; height: number };

function area(shape: Shape): number {
  if (shape.kind === 'circle') return Math.PI * shape.radius ** 2;
  return shape.width * shape.height; // TS knows width/height exist here
}

Wariant Button a Link

Modeluj komponent polimorficzny za pomocą unii rozłącznej opartej na polu as lub variant, aby wymusić poprawne propsy dla każdego przypadku.

type ButtonProps =
  | { as: 'button'; onClick: () => void; disabled?: boolean; children: React.ReactNode }
  | { as: 'a'; href: string; target?: string; children: React.ReactNode };

function ActionButton(props: ButtonProps) {
  if (props.as === 'button') {
    return <button onClick={props.onClick} disabled={props.disabled}>{props.children}</button>;
  }
  return <a href={props.href} target={props.target}>{props.children}</a>;
}

Warianty komponentu Alert

Zamodeluj Alert z innymi wymaganymi danymi dla każdego poziomu ważności.

type AlertProps =
  | { type: 'success'; message: string }
  | { type: 'error'; message: string; onRetry: () => void }
  | { type: 'warning'; message: string; details?: string };

function Alert(props: AlertProps) {
  if (props.type === 'error') {
    return (
      <div className="alert error">
        <p>{props.message}</p>
        <button onClick={props.onRetry}>Retry</button>
      </div>
    );
  }
  return <div className={`alert ${props.type}`}>{props.message}</div>;
}

Zawężanie typów w procedurach obsługi zdarzeń

Unie rozłączne działają także z danymi sterowanymi zdarzeniami — świetnie sprawdzają się w maszynach stanów lub stanie opartym na akcjach.

type LoadingState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: Error };

function DataView<T>({ state }: { state: LoadingState<T> }) {
  if (state.status === 'loading') return <Spinner />;
  if (state.status === 'error') return <p>{state.error.message}</p>;
  if (state.status === 'success') return <pre>{JSON.stringify(state.data)}</pre>;
  return null;
}

Kompletne sprawdzanie z użyciem never

Dodaj sprawdzenie never w gałęzi default, aby TypeScript zgłosił błąd, jeśli dodano nowy element unii, ale go nie obsłużono.

function assertNever(x: never): never {
  throw new Error('Unhandled case: ' + x);
}

function renderIcon(type: AlertProps['type']) {
  switch (type) {
    case 'success': return <CheckIcon />;
    case 'error': return <XIcon />;
    case 'warning': return <WarnIcon />;
    default: return assertNever(type); // TS error if a case is missing
  }
}

Unie rozłączne dla odpowiedzi API

Modeluj kształty odpowiedzi API jako unie rozłączne, aby kod wywołujący obsługiwał ścieżki powodzenia i błędu bez rzutowania typów.

type ApiResult<T> =
  | { ok: true; data: T }
  | { ok: false; error: string; code: number };

async function fetchUser(id: string): Promise<ApiResult<User>> {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) return { ok: false, error: 'Not found', code: res.status };
  return { ok: true, data: await res.json() };
}

Strażnicy typów do zawężania

Używaj niestandardowych strażników typów, aby zawężać unie w bardziej złożonych scenariuszach, w których dyskryminant nie jest prostym sprawdzeniem równości.

function isSuccess<T>(result: ApiResult<T>): result is { ok: true; data: T } {
  return result.ok === true;
}

const result = await fetchUser('1');
if (isSuccess(result)) {
  console.log(result.data.name); // TS knows data exists
}

Unikanie zupy opcjonalnych propsów

Bez unii rozłącznych komponenty gromadzą opcjonalne propsy, które są poprawne tylko w określonych kombinacjach — to mylące i pozbawione bezpiecznego typowania. Unie rozłączne eliminują niemożliwe stany.

// Bad: optional prop soup — invalid combos allowed:
interface BadProps {
  href?: string;
  onClick?: () => void;
  disabled?: boolean;
}

// Good: only valid combos via discriminated union:
type GoodProps =
  | { as: 'a'; href: string }
  | { as: 'button'; onClick: () => void; disabled?: boolean };

Komponowanie unii

Użyj & (części wspólnej), aby dodać wspólne propsy do wszystkich członków unii.

type BaseProps = { className?: string; children: React.ReactNode };

type ButtonVariant =
  | (BaseProps & { variant: 'primary'; onClick: () => void })
  | (BaseProps & { variant: 'link'; href: string });

Rozróżnianie w czasie wykonywania

React używa dyskryminanta w czasie wykonywania, aby wyrenderować właściwy interfejs. TypeScript używa go w czasie kompilacji, aby wymusić poprawne użycie propsów. Obie warstwy są zabezpieczone.

Szybki sprawdzian

Co jest dyskryminantem w unii rozłącznej?

Podsumowanie

Unie rozłączne modelują komponenty z wzajemnie wykluczającymi się zestawami propsów, współdzieląc pole dyskryminanta typowane literałem. Użyj never w gałęzi default do kompletnego sprawdzania. Unie te eliminują nieprawidłowe kombinacje propsów dopuszczane przez opcjonalne propsy, dzięki czemu komponenty same opisują swoje użycie i są bezpieczne typowo.

Często zadawane pytania

Czy lekcja „Rozłączne sumy dla wariantów komponentów” jest bezpłatna?

Tak — pełny tekst „Rozłączne sumy dla wariantów komponentów” 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 React Academy, przejdź na CoddyKit PRO. Kurs React Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Rozłączne sumy dla wariantów komponentów”?

Modelowanie propsów wariantów za pomocą rozłącznych sum, aby TypeScript wymuszał prawidłowe kombinacje propsów. Ćwiczysz React 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ąć React Academy?

Nie wymagamy żadnego doświadczenia. React 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 1 z 4.

Ile czasu zajmuje lekcja „Rozłączne sumy dla wariantów komponentów”?

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 React Academy?

Tak. Każda lekcja React 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. Rozłączne sumy dla wariantów komponentów
  2. Typy warunkowe i mapowane w React
  3. Komponenty polimorficzne z propsem 'as'
  4. Formularze bezpieczne typowo i kontrakty odpowiedzi API
← Powrót do React Academy