Lietuvių

Ištirkite TypeScript diskriminacines sąjungas, galingą įrankį, skirtą patikimoms ir tipų saugioms būsenų mašinoms kurti.

TypeScript Diskriminacinės Sąjungos: Tipų Saugių Būsenų Mašinų Kūrimas

Programinės įrangos kūrimo srityje efektyvus programos būsenos valdymas yra būtinas. Būsenų mašinos suteikia galingą abstrakciją sudėtingoms būsenoms pagrįstoms sistemoms modeliuoti, užtikrindamos nuspėjamą elgesį ir supaprastindamos samprotavimą apie sistemos logiką. TypeScript, turėdamas tvirtą tipų sistemą, siūlo fantastišką mechanizmą tipų saugioms būsenų mašinoms kurti naudojant diskriminacines sąjungas (dar žinomas kaip žymėtos sąjungos arba algebriniai duomenų tipai).

Kas yra diskriminacinės sąjungos?

Diskriminacinė sąjunga yra tipas, kuris atstovauja reikšmei, kuri gali būti viena iš kelių skirtingų tipų. Kiekvienas iš šių tipų, žinomas kaip sąjungos nariai, dalijasi bendru, išskirtiniu ypatumu, vadinamu diskriminatoriumi arba žyme. Šis diskriminatorius leidžia TypeScript tiksliai nustatyti, kuris sąjungos narys šiuo metu yra aktyvus, leidžiantis atlikti galingą tipų tikrinimą ir automatinį užbaigimą.

Pagalvokite apie tai kaip apie šviesoforą. Jis gali būti vienoje iš trijų būsenų: Raudona, Geltona arba Žalia. 'Spalva' ypatybė veikia kaip diskriminatorius, tiksliai pasakydama, kokioje būsenoje yra šviesa.

Kodėl naudoti diskriminacines sąjungas būsenų mašinoms?

Diskriminacinės sąjungos suteikia keletą pagrindinių privalumų kuriant būsenų mašinas TypeScript:

Būsenų mašinos apibrėžimas su diskriminacinėmis sąjungomis

Paaiškinkime, kaip apibrėžti būsenų mašiną naudojant diskriminacines sąjungas su praktiniu pavyzdžiu: užsakymų apdorojimo sistema. Užsakymas gali būti tokiose būsenose: Laukiama, Apdorojama, Išsiųsta ir Pristatyta.

1 žingsnis: Apibrėžkite būsenų tipus

Pirmiausia apibrėžiame atskirus kiekvienos būsenos tipus. Kiekvienas tipas turės 'type' ypatybę, veikiančią kaip diskriminatorius, kartu su visais būsenai specifiniais duomenimis.


interface Pending {
  type: "pending";
  orderId: string;
  customerName: string;
  items: string[];
}

interface Processing {
  type: "processing";
  orderId: string;
  assignedAgent: string;
}

interface Shipped {
  type: "shipped";
  orderId: string;
  trackingNumber: string;
}

interface Delivered {
  type: "delivered";
  orderId: string;
  deliveryDate: Date;
}

2 žingsnis: Sukurkite diskriminacinės sąjungos tipą

Toliau sukuriame diskriminacinę sąjungą sujungdami šiuos atskirus tipus naudodami `|` (sąjungos) operatorių.


type OrderState = Pending | Processing | Shipped | Delivered;

Dabar `OrderState` atstovauja reikšmei, kuri gali būti `Pending`, `Processing`, `Shipped` arba `Delivered`. `type` ypatybė kiekvienoje būsenoje veikia kaip diskriminatorius, leidžiantis TypeScript atskirti jas.

Būsenų perėjimų tvarkymas

Dabar, kai apibrėžėme savo būsenų mašiną, mums reikia mechanizmo pereiti tarp būsenų. Sukurkime `processOrder` funkciją, kuri gauna dabartinę būseną ir veiksmą kaip įvestį ir grąžina naują būseną.


interface Action {
  type: string;
  payload?: any;
}

function processOrder(state: OrderState, action: Action): OrderState {
  switch (state.type) {
    case "pending":
      if (action.type === "startProcessing") {
        return {
          type: "processing",
          orderId: state.orderId,
          assignedAgent: action.payload.agentId,
        };
      }
      return state; // Būsenos keitimas nevyksta

    case "processing":
      if (action.type === "shipOrder") {
        return {
          type: "shipped",
          orderId: state.orderId,
          trackingNumber: action.payload.trackingNumber,
        };
      }
      return state; // Būsenos keitimas nevyksta

    case "shipped":
      if (action.type === "deliverOrder") {
        return {
          type: "delivered",
          orderId: state.orderId,
          deliveryDate: new Date(),
        };
      }
      return state; // Būsenos keitimas nevyksta

    case "delivered":
      // Užsakymas jau pristatytas, daugiau veiksmų nereikia
      return state;

    default:
      // Tai neturėtų nutikti dėl išsamumo tikrinimo
      return state; // Arba išmesti klaidą
  }
}

Paaiškinimas

Išsamumo tikrinimo panaudojimas

TypeScript išsamumo tikrinimas yra galinga funkcija, užtikrinanti, kad apdorosite visas galimas savo būsenų mašinos būsenas. Jei į `OrderState` sąjungą įtrauksite naują būseną, bet pamiršite atnaujinti `processOrder` funkciją, TypeScript pažymės klaidą.

Norėdami įjungti išsamumo tikrinimą, galite naudoti `never` tipą. `default` atveju savo switch sakinyje priskirkite būseną kintamajam, kurio tipas yra `never`.


function processOrder(state: OrderState, action: Action): OrderState {
  switch (state.type) {
    // ... (ankstesni atvejai) ...

    default:
      const _exhaustiveCheck: never = state;
      return _exhaustiveCheck; // Arba išmesti klaidą
  }
}

Jei `switch` sakinys apdoroja visas galimas `OrderState` reikšmes, `_exhaustiveCheck` kintamojo tipas bus `never`, ir kodas bus kompiliuojamas. Tačiau, jei į `OrderState` sąjungą pridėsite naują būseną ir pamiršite ją apdoroti `switch` sakinyje, `_exhaustiveCheck` kintamojo tipas bus kitoks, ir TypeScript išmes kompiliavimo klaidą, įspėdamas apie praleistą atvejį.

Praktiniai pavyzdžiai ir taikymai

Diskriminacinės sąjungos taikomos įvairiuose scenarijuose, ne tik paprastoms užsakymų apdorojimo sistemoms:

Pavyzdys: UI būsenos valdymas

Panagrinėkime paprastą UI komponento, kuris gauna duomenis iš API, būsenos valdymo pavyzdį. Galime apibrėžti šias būsenas:


interface Initial {
  type: "initial";
}

interface Loading {
  type: "loading";
}

interface Success {
  type: "success";
  data: T;
}

interface Error {
  type: "error";
  message: string;
}

type UIState = Initial | Loading | Success | Error;

function renderUI(state: UIState): React.ReactNode {
  switch (state.type) {
    case "initial":
      return 

Spustelėkite mygtuką, kad įkeltumėte duomenis.

; case "loading": return

Įkeliama...

; case "success": return
{JSON.stringify(state.data, null, 2)}
; case "error": return

Klaida: {state.message}

; default: const _exhaustiveCheck: never = state; return _exhaustiveCheck; } }

Šis pavyzdys rodo, kaip diskriminacinės sąjungos gali būti naudojamos efektyviai valdyti skirtingas UI komponento būsenas, užtikrinant, kad UI būtų atvaizduojamas teisingai pagal esamą būseną. `renderUI` funkcija tinkamai tvarko kiekvieną būseną, suteikdama aiškų ir tipo saugų būdą valdyti UI.

Geriausia praktika naudojant diskriminacines sąjungas

Norėdami efektyviai naudoti diskriminacines sąjungas savo TypeScript projektuose, apsvarstykite šias geriausias praktikas:

Pažangūs metodai

Sąlyginiai tipai

Sąlyginiai tipai gali būti derinami su diskriminacinėmis sąjungomis, kad būtų sukurtos dar galingesnės ir lankstesnės būsenų mašinos. Pavyzdžiui, galite naudoti sąlyginius tipus, kad apibrėžtumėte skirtingus grąžinimo tipus funkcijai, pagrįstai pagal esamą būseną.


function getData(state: UIState): T | undefined {
  if (state.type === "success") {
    return state.data;
  }
  return undefined;
}

Ši funkcija naudoja paprastą `if` sakinį, bet gali būti padaryta patikimesnė, naudojant sąlyginius tipus, kad būtų užtikrintas konkretaus tipo visada grąžinimas.

Pagalbiniai tipai

TypeScript pagalbiniai tipai, tokie kaip `Extract` ir `Omit`, gali būti naudingi dirbant su diskriminacinėmis sąjungomis. `Extract` leidžia išskirti konkrečius narius iš sąjungos tipo pagal sąlygą, o `Omit` leidžia pašalinti ypatybes iš tipo.


// Išskirkite "success" būseną iš UIState sąjungos
type SuccessState = Extract, { type: "success" }>;

// Praleiskite 'message' ypatybę iš Error sąsajos
type ErrorWithoutMessage = Omit;

Realaus pasaulio pavyzdžiai įvairiose pramonės šakose

Diskriminacinių sąjungų galia apima įvairias pramonės šakas ir taikymo sritis:

Išvada

TypeScript diskriminacinės sąjungos suteikia galingą ir tipo saugų būdą kurti būsenų mašinas. Aiškiai apibrėždami galimas būsenas ir perėjimus, galite sukurti patikimesnį, prižiūrimą ir suprantamą kodą. Tipų saugumo, išsamumo tikrinimo ir patobulinto kodo užbaigimo derinys daro diskriminacines sąjungas neįkainojamu įrankiu bet kuriam TypeScript kūrėjui, kuris dirba su sudėtingu būsenos valdymu. Priimkite diskriminacines sąjungas savo kitame projekte ir patirkite tipo saugaus būsenos valdymo pranašumus. Kaip parodėme su įvairiais pavyzdžiais nuo e-komercijos iki sveikatos priežiūros ir logistikos iki švietimo, tipo saugaus būsenos valdymo principas per diskriminacines sąjungas yra universaliai taikomas.

Nesvarbu, ar kuriate paprastą UI komponentą, ar sudėtingą įmonės programą, diskriminacinės sąjungos gali padėti efektyviau valdyti būseną ir sumažinti runtime klaidų riziką. Taigi, pasinerkite ir tyrinėkite tipo saugių būsenų mašinų pasaulį su TypeScript!