Modellera tillståndsmaskiner
Representera ändliga tillstånd med diskriminerade unioner.
Modellera tillståndsmaskiner är en gratis lektion i TypeScript Academy på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för TypeScript Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i TypeScript Academy innehåller totalt 4 lektioner.
Tillstånd som en diskriminerad union
UI- och asynkrona flöden har tydligt åtskilda tillstånd: idle, loading, success och error. Genom att modellera dem som en diskriminerad union får varje tillstånd exakt de data det behöver.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
const s: State = { status: "idle" };
console.log(s.status);Datainnehåll per tillstånd
Endast tillståndet success har data; endast error har ett message. Idle och loading innehåller inga extra data, vilket förhindrar att gammal data läcker mellan tillstånd.
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);Rendera varje tillstånd
En funktion som använder switch på status kan rendera rätt utdata för varje tillstånd, med medlemsspecifika fält tillgängliga endast där de finns.
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" }));Definiera övergångar
En tillståndsmaskin rör sig mellan tillstånd genom övergångar. En övergångsfunktion tar det aktuella tillståndet och en händelse och returnerar nästa tillstånd.
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);Modellera även händelser
Händelser kan också vara en diskriminerad union. Varje händelsetyp utlöser en specifik övergång.
type Event =
| { type: "FETCH" }
| { type: "RESOLVE"; data: string }
| { type: "REJECT"; message: string };
const e: Event = { type: "RESOLVE", data: "ok" };
console.log(e.type);En komplett övergångsfunktion
Kombinera unionerna för tillstånd och händelser i en reducer. Genom att använda switch på båda blir varje övergång uttrycklig och typsäker.
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);Ogiltiga tillstånd kan inte representeras
Det går inte att ha data och ett error message samtidigt. Unionens utformning förbjuder motsägelsefulla tillstånd redan genom sin konstruktion.
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");Skydda mot ogiltiga övergångar
Händelser som inte gäller för det aktuella tillståndet kan ignoreras, så att maskinen förblir i ett konsekvent tillstånd i stället för att krascha.
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);Lägg till fullständighetskontroll
Kombinera reducern med assertNever så att tillägg av ett nytt tillstånd eller en ny händelse visar varje ställe som måste uppdateras.
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" }));Start- och sluttillstånd
Ange ett tydligt starttillstånd (ofta idle) och sluttillstånd (success eller error). Det dokumenterar maskinens livscykel.
type State =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
const initial: State = { status: "idle" };
console.log("Start:", initial.status);En komplett liten tillståndsmaskin
Här är hela flödet: börja i idle, gå till loading vid hämtning och övergå till success när hämtningen slutförs. Typerna håller varje steg korrekt.
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 : "");Snabbtest: tillståndsmaskiner
Testa era kunskaper om modellering av tillståndsmaskiner.
Sammanfattning: modellera tillståndsmaskiner
Ni har modellerat idle/loading/success/error som en diskriminerad union, skrivit typsäkra övergångar över unioner av tillstånd och händelser samt använt fullständighetskontroll för att hålla maskinen korrekt när den växer.
type State = { status: "idle" } | { status: "loading" } | { status: "success"; data: string };
const s: State = { status: "success", data: "done" };
console.log(s.status === "success" ? s.data : "");Lär dig TypeScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 101
- Lektioner
- 352
Vanliga frågor
Är lektionen ”Modellera tillståndsmaskiner” gratis?
Ja – hela texten till ”Modellera tillståndsmaskiner” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i TypeScript Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i TypeScript Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Modellera tillståndsmaskiner”?
Representera ändliga tillstånd med diskriminerade unioner. Ni övar på TypeScript Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig TypeScript Academy?
Du behöver inga förkunskaper. Utbildningen i TypeScript Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Modellera tillståndsmaskiner”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här TypeScript Academy-lektionen?
Ja. Varje TypeScript Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Bygga diskriminerade unioner
- Begränsning utifrån diskriminanten
- Fullständighetskontroll med never
- Modellera tillståndsmaskiner