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:
- Tüübikindlus: Kompilaator saab kontrollida, et kõik võimalikud olekud ja üleminekud on korrektselt käsitletud, vältides ootamatute olekuüleminekutega seotud käitusaja vigu. See on eriti kasulik suurtes ja keerukates rakendustes.
- Ammendavuse kontroll: TypeScript suudab tagada, et teie kood käsitleb kõiki olekumasina võimalikke olekuid, andes kompileerimisajal teada, kui mõni olek on tingimuslauses või switch-case'is vahele jäänud. See aitab vältida ootamatut käitumist ja muudab teie koodi robustsemaks.
- Parem loetavus: Diskrimineeritud ühendid defineerivad selgelt süsteemi võimalikud olekud, muutes koodi lihtsamini mõistetavaks ja hooldatavaks. Olekute selgesõnaline esitus parandab koodi selgust.
- Täiustatud koodilõpetamine: TypeScript'i intellisense pakub intelligentseid koodilõpetamise soovitusi, mis põhinevad hetkeolekul, vähendades vigade tõenäosust ja kiirendades arendusprotsessi.
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
- Funktsioon `processOrder` võtab sisendiks hetke `OrderState` ja `Action`'i.
- See kasutab `switch` lauset hetkeoleku määramiseks `state.type` diskriminandi alusel.
- Iga `case`'i sees kontrollib see `action.type`'i, et teha kindlaks, kas käivitatakse kehtiv üleminek.
- Kui leitakse kehtiv üleminek, tagastab see uue olekuobjekti koos vastava `type`'i ja andmetega.
- Kui kehtivat üleminekut ei leita, tagastab see hetkeoleku (või viskab vea, sõltuvalt soovitud käitumisest).
- `default` haru on lisatud täielikkuse huvides ja ideaalis ei tohiks selleni kunagi jõuda tänu TypeScript'i ammendavuse kontrollile.
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:
- Kasutajaliidese oleku haldamine: Kasutajaliidese komponendi oleku modelleerimine (nt laadimine, õnnestumine, viga).
- Võrgupäringute käsitlemine: Võrgupäringu erinevate etappide esitamine (nt algne, pooleli, õnnestus, ebaõnnestus).
- Vormi valideerimine: Vormiväljade kehtivuse ja vormi üldise oleku jälgimine.
- Mänguarendus: Mängutegelase või objekti erinevate olekute defineerimine.
- Autentimisvood: Kasutaja autentimisolekute haldamine (nt sisse logitud, välja logitud, ootab kinnitust).
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:
- Valige tähendusrikkad diskriminantide nimed: Valige diskriminantide nimed, mis viitavad selgelt omaduse eesmärgile (nt `type`, `state`, `status`).
- Hoidke olekuandmed minimaalsed: Iga olek peaks sisaldama ainult sellele konkreetsele olekule asjakohaseid andmeid. Vältige ebavajalike andmete salvestamist olekutesse.
- Kasutage ammendavuse kontrolli: Lubage alati ammendavuse kontroll, et tagada kõigi võimalike olekute käsitlemine.
- Kaaluge olekuhaldus teegi kasutamist: Keeruliste olekumasinate jaoks kaaluge spetsiaalse olekuhaldus teegi, näiteks XState, kasutamist, mis pakub täiustatud funktsioone nagu olekukaardid, hierarhilised olekud ja paralleelsed olekud. Lihtsamate stsenaariumide puhul võivad diskrimineeritud ühendid aga olla piisavad.
- Dokumenteerige oma olekumasin: Dokumenteerige selgelt oma olekumasina erinevad olekud, üleminekud ja tegevused, et parandada hooldatavust ja koostööd.
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:
- E-kaubandus (globaalne): Globaalses e-kaubanduse platvormis saab tellimuse staatust esitada diskrimineeritud ühenditega, käsitledes olekuid nagu "MakseOotel", "Töötlemisel", "Saadetud", "Transpordis", "KätteToimetatud" ja "Tühistatud". See tagab korrektse jälgimise ja suhtluse erinevates riikides, kus on erinev transpordilogistika.
- Finantsteenused (rahvusvaheline pangandus): Tehingu olekute nagu "AutoriseerimiseOotel", "Autoriseeritud", "Töötlemisel", "Lõpetatud", "Ebaõnnestunud" haldamine on kriitilise tähtsusega. Diskrimineeritud ühendid pakuvad robustset viisi nende olekute käsitlemiseks, järgides erinevaid rahvusvahelisi pangandusregulatsioone.
- Tervishoid (patsientide kaugjälgimine): Patsiendi tervisliku seisundi esitamine olekutega nagu "Normaalne", "Hoiatus", "Kriitiline" võimaldab õigeaegset sekkumist. Globaalselt hajutatud tervishoiusüsteemides suudavad diskrimineeritud ühendid tagada andmete ühtse tõlgendamise asukohast olenemata.
- Logistika (globaalne tarneahel): Saadetise staatuse jälgimine üle rahvusvaheliste piiride hõlmab keerukaid töövooge. Olekud nagu "Tollivormistus", "Transpordis", "Jaotuskeskuses", "KätteToimetatud" sobivad ideaalselt diskrimineeritud ühenditega realiseerimiseks.
- Haridus (veebipõhised õppeplatvormid): Kursusele registreerumise staatuse haldamine olekutega nagu "Registreerunud", "Pooleli", "Lõpetatud", "Katkestatud" võib pakkuda sujuvamat õppekogemust, mis on kohandatav erinevatele haridussüsteemidele kogu maailmas.
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!