TypeScript Academy · Oppitunti

Tilakoneiden mallintaminen

Esittäkää rajalliset tilat diskriminoitujen unionien avulla.

Oppitunti 4/413 vaihetta

Tilakoneiden mallintaminen on ilmainen TypeScript Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu TypeScript Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. TypeScript Academy-kurssilla on yhteensä 4 oppituntia.

Tilat diskriminoituna unionina

Käyttöliittymillä ja asynkronisilla työnkuluilla on erillisiä tiloja: idle, loading, success ja error. Kun mallinnat ne diskriminoituna unionina, jokainen tila sisältää täsmälleen tarvitsemansa tiedot.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

const s: State = { status: "idle" };
console.log(s.status);

Tiedot kullekin tilalle

Vain success-tilalla on data; vain error-tilalla on message. Idle- ja loading-tilat eivät sisällä ylimääräisiä tietoja, mikä estää vanhentuneiden tietojen vuotamisen tilasta toiseen.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: number[] }
  | { status: "error"; message: string };

const ok: State = { status: "success", data: [1, 2, 3] };
console.log(ok.status, "data" in ok ? ok.data : null);

Kunkin tilan näyttäminen

status-arvon perusteella haarautuva funktio voi näyttää kullekin tilalle oikean tuloksen. Jäsenkohtaiset kentät ovat käytettävissä vain siellä, missä ne todella ovat olemassa.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

function view(s: State): string {
  switch (s.status) {
    case "idle": return "Ready";
    case "loading": return "Loading...";
    case "success": return "Got: " + s.data;
    case "error": return "Failed: " + s.message;
  }
}
console.log(view({ status: "success", data: "users" }));

Siirtymien määrittäminen

Tilakone siirtyy tilasta toiseen siirtymien avulla. Siirtymäfunktio ottaa vastaan nykyisen tilan ja tapahtuman ja palauttaa seuraavan tilan.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

function start(s: State): State {
  if (s.status === "idle") return { status: "loading" };
  return s;
}
console.log(start({ status: "idle" }).status);

Myös tapahtumien mallintaminen

Myös tapahtumat voivat muodostaa diskriminoidun unionin. Kukin tapahtumatyyppi käynnistää tietyn siirtymän.

type Event =
  | { type: "FETCH" }
  | { type: "RESOLVE"; data: string }
  | { type: "REJECT"; message: string };

const e: Event = { type: "RESOLVE", data: "ok" };
console.log(e.type);

Täydellinen siirtymäfunktio

Yhdistä tila- ja tapahtumaunionit yhteen reduceria käyttävään toteutukseen. Molempien perusteella haarautuminen pitää jokaisen siirtymän eksplisiittisenä ja tyyppiturvallisena.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };
type Event =
  | { type: "FETCH" }
  | { type: "RESOLVE"; data: string }
  | { type: "REJECT"; message: string };

function reduce(s: State, e: Event): State {
  if (e.type === "FETCH") return { status: "loading" };
  if (e.type === "RESOLVE") return { status: "success", data: e.data };
  return { status: "error", message: e.message };
}
console.log(reduce({ status: "idle" }, { type: "FETCH" }).status);

Virheellisiä tiloja ei voi esittää

Sinulla ei voi olla data-arvoa ja error message-arvoa samanaikaisesti. Unionin rakenne estää ristiriitaiset tilat jo muodostusvaiheessa.

type State =
  | { status: "success"; data: string }
  | { status: "error"; message: string };

// const bad: State = { status: "success", data: "x", message: "y" };
// Allowed extra props would be flagged in strict object checks.
console.log("no contradictory states");

Virheellisten siirtymien estäminen

Voit ohittaa tapahtumat, jotka eivät koske nykyistä tilaa. Näin kone pysyy johdonmukaisessa tilassa kaatumisen sijaan.

type State = { status: "idle" } | { status: "loading" };
type Event = { type: "FETCH" } | { type: "CANCEL" };

function reduce(s: State, e: Event): State {
  if (s.status === "loading" && e.type === "CANCEL") return { status: "idle" };
  if (s.status === "idle" && e.type === "FETCH") return { status: "loading" };
  return s; // ignore invalid combos
}
console.log(reduce({ status: "loading" }, { type: "CANCEL" }).status);

Kattavuuden lisääminen

Yhdistä reduceria käyttävään toteutukseen assertNever, jotta uuden tilan tai tapahtuman lisääminen paljastaa kaikki päivitettävät kohdat.

function assertNever(x: never): never { throw new Error("unhandled"); }
type State = { status: "idle" } | { status: "loading" } | { status: "done"; data: string };

function view(s: State): string {
  switch (s.status) {
    case "idle": return "idle";
    case "loading": return "loading";
    case "done": return s.data;
    default: return assertNever(s);
  }
}
console.log(view({ status: "done", data: "ok" }));

Alku- ja lopputilat

Määritä selkeä alkutila, usein idle, sekä lopputilat, kuten success tai error. Näin dokumentoit tilakoneen elinkaaren.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

const initial: State = { status: "idle" };
console.log("Start:", initial.status);

Täydellinen pieni tilakone

Tässä on koko kierto: aloita idle-tilasta, siirry fetch-toiminnolla loading-tilaan ja ratkaise tilaksi success. Tyypit pitävät jokaisen vaiheen johdonmukaisena.

type State = { status: "idle" } | { status: "loading" } | { status: "success"; data: string };
type Event = { type: "FETCH" } | { type: "RESOLVE"; data: string };

function reduce(s: State, e: Event): State {
  if (e.type === "FETCH") return { status: "loading" };
  return { status: "success", data: e.data };
}
let st: State = { status: "idle" };
st = reduce(st, { type: "FETCH" });
st = reduce(st, { type: "RESOLVE", data: "hi" });
console.log(st.status, st.status === "success" ? st.data : "");

Pikatarkistus: tilakoneet

Testaa, miten hyvin ymmärrät tilakoneiden mallintamisen.

Kertaus: tilakoneiden mallintaminen

Mallinsit idle-, loading-, success- ja error-tilat diskriminoituna unionina, kirjoitit tyyppiturvalliset siirtymät tila- ja tapahtumaunioneille sekä käytit kattavuustarkistusta pitääksesi tilakoneen oikeellisena sen kasvaessa.

type State = { status: "idle" } | { status: "loading" } | { status: "success"; data: string };
const s: State = { status: "success", data: "done" };
console.log(s.status === "success" ? s.data : "");
Aloita maksutta

Opi TypeScript tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
101
Oppitunnit
352

Usein kysytyt kysymykset

Onko oppitunti ”Tilakoneiden mallintaminen” ilmainen?

Kyllä – oppitunnin ”Tilakoneiden mallintaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko TypeScript Academy-kurssin, päivitä CoddyKit PROhon. TypeScript Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Tilakoneiden mallintaminen”?

Esittäkää rajalliset tilat diskriminoitujen unionien avulla. Harjoittelet TypeScript Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni TypeScript Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin TypeScript Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Tilakoneiden mallintaminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä TypeScript Academy-oppitunnilla?

Kyllä. Jokainen TypeScript Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Diskriminoitujen unionien rakentaminen
  2. Tyypin supistaminen diskriminoijan perusteella
  3. Kattavuuden tarkistus never-tyypillä
  4. Tilakoneiden mallintaminen
← Takaisin: TypeScript Academy