Eesti

Avastage TypeScript'i diskrimineeritud ühendid – võimas tööriist robustsete ja tüübikindlate olekumasinate loomiseks. Õppige, kuidas defineerida olekuid, käsitleda üleminekuid ja parandada koodi usaldusväärsust.

TypeScript'i diskrimineeritud ühendid: tüübikindlate olekumasinate ehitamine

Tarkvaraarenduse maailmas on rakenduse oleku tõhus haldamine ülioluline. Olekumasinad pakuvad võimsat abstraktsiooni keerukate olekupõhiste süsteemide modelleerimiseks, tagades prognoositava käitumise ja lihtsustades süsteemi loogika mõistmist. TypeScript oma robustse tüübisüsteemiga pakub fantastilist mehhanismi tüübikindlate olekumasinate ehitamiseks, kasutades diskrimineeritud ühendeid (tuntud ka kui sildistatud ühendid või algebralised andmetüübid).

Mis on diskrimineeritud ühendid?

Diskrimineeritud ühend on tüüp, mis esindab väärtust, mis võib olla üks mitmest erinevast tüübist. Igaühel neist tüüpidest, mida nimetatakse ühendi liikmeteks, on ühine ja eristuv omadus, mida nimetatakse diskriminandiks või sildiks. See diskriminant võimaldab TypeScriptil täpselt kindlaks teha, milline ühendi liige on hetkel aktiivne, võimaldades võimsat tüübikontrolli ja automaatset koodilõpetamist.

Mõelge sellele nagu valgusfoorile. See võib olla ühes kolmest olekust: punane, kollane või roheline. Omadus 'värv' toimib diskriminandina, öeldes meile täpselt, millises olekus valgusfoor on.

Miks kasutada olekumasinate jaoks diskrimineeritud ühendeid?

Diskrimineeritud ühendid toovad TypeScriptis olekumasinate ehitamisel mitmeid olulisi eeliseid:

Olekumasina defineerimine diskrimineeritud ühenditega

Illustreerime, kuidas defineerida olekumasinat diskrimineeritud ühendite abil praktilise näite varal: tellimuste töötlemise süsteem. Tellimus võib olla järgmistes olekutes: Ootel, Töötlemisel, Saadetud ja Kätte toimetatud.

Samm 1: Defineerige olekutüübid

Esmalt defineerime iga oleku jaoks eraldi tüübid. Igal tüübil on diskriminandina toimiv omadus `type` koos olekuspetsiifiliste andmetega.


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;
}

Samm 2: Looge diskrimineeritud ühendi tüüp

Järgmisena loome diskrimineeritud ühendi, kombineerides need individuaalsed tüübid, kasutades `|` (unioni) operaatorit.


type OrderState = Pending | Processing | Shipped | Delivered;

Nüüd esindab `OrderState` väärtust, mis võib olla kas `Pending`, `Processing`, `Shipped` või `Delivered`. Igas olekus olev omadus `type` toimib diskriminandina, võimaldades TypeScriptil nende vahel vahet teha.

Olekuüleminekute käsitlemine

Nüüd, kui oleme oma olekumasina defineerinud, vajame mehhanismi olekute vahel liikumiseks. Loome funktsiooni `processOrder`, mis võtab sisendiks hetkeoleku ja tegevuse ning tagastab uue oleku.


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; // No state change

    case "processing":
      if (action.type === "shipOrder") {
        return {
          type: "shipped",
          orderId: state.orderId,
          trackingNumber: action.payload.trackingNumber,
        };
      }
      return state; // No state change

    case "shipped":
      if (action.type === "deliverOrder") {
        return {
          type: "delivered",
          orderId: state.orderId,
          deliveryDate: new Date(),
        };
      }
      return state; // No state change

    case "delivered":
      // Order is already delivered, no further actions
      return state;

    default:
      // This should never happen due to exhaustiveness checking
      return state; // Or throw an error
  }
}

Selgitus

Ammendavuse kontrolli ärakasutamine

TypeScript'i ammendavuse kontroll on võimas funktsioon, mis tagab, et käsitlete kõiki võimalikke olekuid oma olekumasinas. Kui lisate `OrderState` ühendisse uue oleku, kuid unustate uuendada `processOrder` funktsiooni, annab TypeScript veateate.

Ammendavuse kontrolli lubamiseks saate kasutada `never` tüüpi. Oma switch-lause `default` harus määrake olek `never` tüüpi muutujale.


function processOrder(state: OrderState, action: Action): OrderState {
  switch (state.type) {
    // ... (previous cases) ...

    default:
      const _exhaustiveCheck: never = state;
      return _exhaustiveCheck; // Or throw an error
  }
}

Kui `switch` lause käsitleb kõiki võimalikke `OrderState` väärtusi, on muutuja `_exhaustiveCheck` tüüpi `never` ja kood kompileerub. Kui aga lisate `OrderState` ühendisse uue oleku ja unustate seda `switch` lauses käsitleda, on `_exhaustiveCheck` muutuja teist tüüpi ja TypeScript viskab kompileerimisaja vea, teavitades teid puuduvast harust.

Praktilised näited ja rakendused

Diskrimineeritud ühendid on rakendatavad laias valikus stsenaariumides peale lihtsate tellimuste töötlemise süsteemide:

Näide: kasutajaliidese oleku haldamine

Vaatleme lihtsat näidet kasutajaliidese komponendi oleku haldamisest, mis hangib andmeid API-st. Saame defineerida järgmised olekud:


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 

Click the button to load data.

; case "loading": return

Loading...

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

Error: {state.message}

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

See näide demonstreerib, kuidas diskrimineeritud ühendeid saab kasutada kasutajaliidese komponendi erinevate olekute tõhusaks haldamiseks, tagades, et kasutajaliides renderdatakse korrektselt vastavalt hetkeolekule. Funktsioon `renderUI` käsitleb iga olekut asjakohaselt, pakkudes selget ja tüübikindlat viisi kasutajaliidese haldamiseks.

Parimad praktikad diskrimineeritud ühendite kasutamisel

Et diskrimineeritud ühendeid oma TypeScripti projektides tõhusalt kasutada, kaaluge järgmisi parimaid praktikaid:

Täiustatud tehnikad

Tingimuslikud tüübid

Tingimuslikke tüüpe saab kombineerida diskrimineeritud ühenditega, et luua veelgi võimsamaid ja paindlikumaid olekumasinaid. Näiteks saate kasutada tingimuslikke tüüpe, et defineerida funktsioonile erinevaid tagastustüüpe vastavalt hetkeolekule.


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

See funktsioon kasutab lihtsat `if` lauset, kuid seda saaks muuta robustsemaks, kasutades tingimuslikke tüüpe, et tagada alati kindla tüübi tagastamine.

Abistavad tüübid

TypeScript'i abistavad tüübid, nagu `Extract` ja `Omit`, võivad olla kasulikud diskrimineeritud ühenditega töötamisel. `Extract` võimaldab teil tingimuse alusel eraldada ühenditüübist konkreetseid liikmeid, samas kui `Omit` võimaldab teil tüübist omadusi eemaldada.


// Extract the "success" state from the UIState union
type SuccessState = Extract, { type: "success" }>;

// Omit the 'message' property from the Error interface
type ErrorWithoutMessage = Omit;

Reaalse maailma näited erinevatest tööstusharudest

Diskrimineeritud ühendite võimsus laieneb erinevatele tööstusharudele ja rakendusvaldkondadele:

Kokkuvõte

TypeScript'i diskrimineeritud ühendid pakuvad võimsat ja tüübikindlat viisi olekumasinate ehitamiseks. Selgelt defineerides võimalikud olekud ja üleminekud, saate luua robustsemat, hooldatavamat ja arusaadavamat koodi. Tüübikindluse, ammendavuse kontrolli ja täiustatud koodilõpetamise kombinatsioon muudab diskrimineeritud ühendid hindamatuks tööriistaks igale TypeScripti arendajale, kes tegeleb keeruka olekuhaldusega. Võtke diskrimineeritud ühendid oma järgmises projektis kasutusele ja kogege omal nahal tüübikindla olekuhalduse eeliseid. Nagu oleme näidanud erinevate näidetega e-kaubandusest tervishoiu ja logistikast hariduseni, on tüübikindla olekuhalduse põhimõte diskrimineeritud ühendite kaudu universaalselt rakendatav.

Olenemata sellest, kas ehitate lihtsat kasutajaliidese komponenti või keerukat ettevõtterakendust, aitavad diskrimineeritud ühendid teil olekut tõhusamalt hallata ja vähendada käitusaja vigade riski. Seega, sukelduge sisse ja avastage tüübikindlate olekumasinate maailma TypeScriptiga!