React Forum
Blog & Guide Responses
Jan 14, 2023 · 04:00 AM

TypeScript: Narrowing - discussion (2023-01-14)

Started by Morgan Patel
externaltypescriptnarrowingdiscriminated unionsguardsstate machines

TS narrowing is one of those topics that seems "language-y" until you start modeling UI state lanes and intent objects. I'm curious what narrowing patterns people rely on most in React code, especially when the goal is to keep state transitions and evidence rendering honest.

Read the handbook

Do you use discriminated unions for UI lanes (pending/ok/error), or do you keep separate booleans? What narrowing patterns keep reducers/intent handlers readable? Have you used custom type guards in app code, or do you mostly stick to in / typeof / instanceof?

Comments (12)

Back to latest
Marisol Vega
Jan 18, 2023 · 08:11 PM

Discriminated unions for lanes are the biggest win. Booleans inevitably drift.

Dmitri Kline
Feb 01, 2023 · 06:52 AM

Reducer readability improves when the union is the *only* input shape you accept:

ts
type Lane = { kind: 'idle' } | { kind: 'pending'; startedAt: number } | { kind: 'error'; message: string } | { kind: 'ok' };

function renderLane(l: Lane) {
  if (l.kind === 'pending') return `pending:${l.startedAt}`;
  if (l.kind === 'error') return `error:${l.message}`;
  return l.kind;
}

Now your evidence rendering is type-checked too.

Keira Santos
Feb 18, 2023 · 10:40 AM

Counterpoint: unions can get annoying if you over-model every little thing.

We keep unions for state machines and keep the rest simple.

Morgan Patel
Feb 21, 2023 · 11:10 PM

Same. The threshold for me is: do we need this to be observable and replayable?

If yes, model it. If no, keep it lightweight.

Grace McCoy
Mar 09, 2023 · 05:21 AM

Custom type guards show up mostly at boundaries (API payload validation).

Inside the app I mostly use discriminants and in checks.

Jasper Nguyen
Mar 27, 2023 · 07:44 PM

A pattern we use: prefer narrowing by a stable type or kind field over typeof checks.

It makes logs and evidence consistent too.

Camille Duarte
Apr 20, 2023 · 11:18 AM

This also helps with "route contracts" in these sites.

If route keys are unions, you can keep UI motion explicit without allowing arbitrary strings.

Owen Price
May 18, 2023 · 06:02 AM

We still have a couple of isLoading booleans and they always end up in impossible combinations.

Every time we replace one with a union lane, the code gets calmer.

Lina Ortega
Jul 02, 2023 · 10:55 PM

Docs tie-in: narrowing is a good companion to the "evidence" posture.

If the state is modeled, your evidence rendering becomes correct-by-construction.

Related: API Reference and Testing and Debugging.

Benji Rios
Sep 19, 2023 · 04:44 AM

One mistake: people use narrowing but still allow any to enter through JSON boundaries.

If you don't validate the boundary, narrowing isn't saving you.

Theo Bennett
Jan 12, 2024 · 01:13 PM

I like the handbook's emphasis that narrowing is just "making the type more specific".

In UI code that often means: pick one lane and commit to it, rather than juggling booleans.

Amina Farouk
Jun 11, 2024 · 06:33 AM

We also use narrowing patterns in event handlers (currentTarget guards, optional chaining) to avoid a bunch of runtime checks.

Not glamorous, but it keeps UI code tidy.

Tomas Rivera
Feb 02, 2025 · 08:05 PM

State lanes + evidence rendering is where narrowing feels most valuable to me. It's not just type safety; it's UX clarity.