0Pricing
TypeScript Academy · Aula

Modelando Máquinas de Estado

Represente estados finitos com uniões discriminadas.

Modelando Máquinas de Estado é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de TypeScript Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de TypeScript Academy inclui 4 aulas no total.

Estados como uma união discriminada

Interfaces de usuário e fluxos assíncronos têm estados distintos: inativo, carregando, sucesso e erro. Modelá-los como uma união discriminada faz com que cada estado contenha exatamente os dados de que precisa.

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

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

Dados específicos de cada estado

Apenas o estado success tem data; apenas error tem message. Os estados inativo e carregando não contêm nada adicional, o que impede que dados antigos vazem entre os estados.

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

Renderização de cada estado

Uma função que faz uma seleção sobre status pode renderizar a saída correta para cada estado, com os campos dos membros disponíveis apenas onde eles existem.

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

Definição de transições

Uma máquina de estados move-se entre estados por meio de transições. Uma função de transição recebe o estado atual e um evento e devolve o próximo estado.

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

Modelagem dos eventos também

Os próprios eventos também podem ser uma união discriminada. Cada tipo de evento dispara uma transição específica.

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

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

Uma função de transição completa

Combine uniões de estados e de eventos em um único redutor. Fazer seleções sobre ambos mantém cada transição explícita e segura quanto aos tipos.

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

Estados ilegais não podem ser representados

Você não pode ter data e uma error message ao mesmo tempo. O design da união proíbe estados contraditórios por construção.

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");

Proteção contra transições inválidas

Você pode ignorar eventos que não se aplicam ao estado atual, mantendo a máquina em um estado consistente em vez de fazê-la falhar.

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

Adição da exaustividade

Associe o redutor a assertNever para que a adição de um novo estado ou evento revele todos os locais que você precisa atualizar.

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

Estados inicial e final

Defina um estado inicial claro, geralmente idle, e estados finais, como success ou error. Isso documenta o ciclo de vida da máquina.

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

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

Uma máquina de estados pequena e completa

Aqui está o ciclo completo: comece inativo, faça uma busca para passar ao carregamento e conclua com sucesso quando a operação for resolvida. Os tipos mantêm cada etapa correta.

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 : "");

Verificação rápida: máquinas de estados

Teste sua compreensão da modelagem de máquinas de estados.

Recapitulação: modelagem de máquinas de estados

Você modelou os estados inativo, carregando, sucesso e erro como uma união discriminada, escreveu transições seguras quanto aos tipos sobre uniões de estados e eventos e usou a exaustividade para manter a máquina correta à medida que ela cresce.

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

Perguntas Frequentes

A aula “Modelando Máquinas de Estado” é grátis?

Sim — o texto completo de “Modelando Máquinas de Estado” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de TypeScript Academy, atualize para CoddyKit PRO. O curso de TypeScript Academy inclui 4 aulas no total.

O que vou aprender em “Modelando Máquinas de Estado”?

Represente estados finitos com uniões discriminadas. Você pratica TypeScript Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar TypeScript Academy?

Nenhuma experiência prévia é necessária. TypeScript Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Modelando Máquinas de Estado”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de TypeScript Academy?

Sim. Cada aula de TypeScript Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Construindo Uniões Discriminadas
  2. Restrição pelo Discriminante
  3. Verificação de Exaustividade com never
  4. Modelando Máquinas de Estado
← Voltar para TypeScript Academy