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:
- Tipų saugumas: Kompiliatorius gali patikrinti, ar visos įmanomos būsenos ir perėjimai yra tvarkomi teisingai, išvengiant runtime klaidų, susijusių su netikėtais būsenų perėjimais. Tai ypač naudinga didelėse, sudėtingose programose.
- Išsamumo tikrinimas: TypeScript gali užtikrinti, kad jūsų kodas apdoroja visas galimas būsenų mašinos būsenas, kompiliavimo metu įspėdamas jus, jei sąlyginiame sakinyje arba switch atveju praleista būsena. Tai padeda išvengti netikėto elgesio ir padaro jūsų kodą patikimesnį.
- Pagerintas skaitymas: Diskriminacinės sąjungos aiškiai apibrėžia galimas sistemos būsenas, todėl kodą lengviau suprasti ir prižiūrėti. Aiškus būsenų atvaizdavimas pagerina kodo aiškumą.
- Patobulintas kodo užbaigimas: TypeScript intellisense pateikia protingus kodo užbaigimo pasiūlymus, pagrįstus esama būsena, sumažindamas klaidų tikimybę ir paspartindamas kūrimą.
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
- `processOrder` funkcija gauna dabartinę `OrderState` ir `Action` kaip įvestį.
- Ji naudoja `switch` sakinį, kad nustatytų esamą būseną, remdamasi `state.type` diskriminatoriumi.
- Kiekviename `case` ji tikrina `action.type`, kad nustatytų, ar suaktyvintas galiojantis perėjimas.
- Jei randamas galiojantis perėjimas, jis grąžina naują būsenos objektą su atitinkamu `type` ir duomenimis.
- Jei nerandamas galiojantis perėjimas, jis grąžina esamą būseną (arba išmeta klaidą, priklausomai nuo norimo elgesio).
- `default` atvejis yra įtrauktas dėl išsamumo ir idealiai neturėtų būti pasiektas dėl TypeScript išsamumo tikrinimo.
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:
- UI būsenos valdymas: UI komponento būsenos modeliavimas (pvz., įkeliama, sėkminga, klaida).
- Tinklo užklausų tvarkymas: Atstovauja skirtingus tinklo užklausos etapus (pvz., pradinis, vykdomas, sėkmingas, nesėkmingas).
- Formų patvirtinimas: Formos laukų ir bendros formos būsenos galiojimo stebėjimas.
- Žaidimų kūrimas: Apibrėžia skirtingas žaidimo veikėjo arba objekto būsenas.
- Autentifikavimo srautai: Valdo vartotojų autentifikavimo būsenas (pvz., prisijungęs, atsijungęs, laukiama patvirtinimo).
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:
- Pasirinkite prasmingus diskriminatorių pavadinimus: Pasirinkite diskriminatorių pavadinimus, kurie aiškiai rodo ypatybės paskirtį (pvz., `type`, `state`, `status`).
- Laikykite būsenos duomenis minimalius: Kiekviena būsena turėtų apimti tik tuos duomenis, kurie yra aktualūs tai konkrečiai būsenai. Venkite saugoti nereikalingus duomenis būsenose.
- Naudokite išsamumo tikrinimą: Visada įjunkite išsamumo tikrinimą, kad užtikrintumėte, jog tvarkote visas galimas būsenas.
- Apsvarstykite būsenos valdymo bibliotekos naudojimą: Sudėtingoms būsenų mašinoms apsvarstykite galimybę naudoti specialią būsenos valdymo biblioteką, pvz., XState, kuri suteikia pažangias funkcijas, tokias kaip būsenų diagramos, hierarchinės būsenos ir lygiagrečios būsenos. Tačiau, paprastesniuose scenarijuose diskriminacinių sąjungų gali pakakti.
- Dokumentuokite savo būsenų mašiną: Aiškiai dokumentuokite skirtingas savo būsenų mašinos būsenas, perėjimus ir veiksmus, kad pagerintumėte priežiūrą ir bendradarbiavimą.
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:
- E-komercija (Pasaulinė): Pasaulinėje e-komercijos platformoje užsakymo būsena gali būti atstovaujama diskriminacinėmis sąjungomis, tvarkant tokias būsenas kaip "LaukiamasMokėjimas", "Apdorojama", "Išsiųsta", "Pakeliui", "Pristatyta" ir "Atšaukta". Tai užtikrina teisingą stebėjimą ir bendravimą įvairiose šalyse, kuriose taikoma skirtinga siuntimo logistika.
- Finansinės paslaugos (Tarptautinė bankininkystė): Svarbu valdyti operacijų būsenas, pvz., "LaukiamaAutorizacija", "Autorizuota", "Apdorojama", "Užbaigta", "Nepavyko". Diskriminacinės sąjungos suteikia patikimą būdą tvarkyti šias būsenas, laikantis įvairių tarptautinių bankininkystės taisyklių.
- Sveikatos priežiūra (Nuotolinis pacientų stebėjimas): Paciento sveikatos būsenos atvaizdavimas naudojant būsenas, pvz., "Normali", "Įspėjimas", "Kritinė", leidžia laiku įsikišti. Visame pasaulyje paskirstytose sveikatos priežiūros sistemose diskriminacinės sąjungos gali užtikrinti nuoseklų duomenų interpretavimą, neatsižvelgiant į vietą.
- Logistika (Pasaulinė tiekimo grandinė): Siuntos būsenos stebėjimas per tarptautines sienas apima sudėtingus darbų srautus. Būsenos, tokios kaip "MuitinėsApmuitas", "Pakeliui", "DistribucinisCentras", "Pristatyta", puikiai tinka diskriminacinių sąjungų įgyvendinimui.
- Švietimas (Internetinės mokymosi platformos): Kurso registracijos būsenos valdymas su būsenomis, pvz., "Užregistruota", "Vykdoma", "Užbaigta", "Praleista" gali suteikti supaprastintą mokymosi patirtį, pritaikomą įvairioms švietimo sistemoms visame pasaulyje.
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!