Skip to main content
← ⚑ JavaScript & the browserΒ·Module C5 Β· Lesson 7
TaskDefine @typedef Ok ({kind:"ok", value:number}), Err ({kind:"err", message:string}), Result = Ok | Err. Write describe(r): "got <value>" or "fail: <message>". Log describe({kind:"ok",value:42}), describe({kind:"err",message:"boom"}).

Discriminated unions in JSDoc

175 XP12 min
Theory

Two shapes, one name

API responses often have a tag field that decides the shape:

{ "kind": "ok",  "value": 42 }
{ "kind": "err", "message": "boom" }

This is a discriminated union: same union type, the kind field picks which branch you're in. In JSDoc you express it as two @typedefs plus a third that unions them:

/**
 * @typedef {Object} Ok
 * @property {"ok"} kind
 * @property {number} value
 */
/**
 * @typedef {Object} Err
 * @property {"err"} kind
 * @property {string} message
 */
/** @typedef {Ok | Err} Result */

How the editor narrows

When you check the discriminator, the editor narrows the type:

/** @param {Result} r */
function describe(r) {
  if (r.kind === "ok")  return "got " + r.value;     // r is Ok here
  if (r.kind === "err") return "fail: " + r.message; // r is Err here
}

Inside each branch, IntelliSense only suggests the fields valid for that shape β€” same as TypeScript discriminated unions.

The take-home

Tagged unions encode "API guarantees this OR that, never both" directly in the type. Cheap, robust, no compiler required.

πŸ”’

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β€” card required, cancel anytime.

Sign up β€” free trial β†’

First 10 lessons in each track are free. No card needed for those.

← PreviousNext lesson β†’

Get one Python or web tip a day β€” by email

Short, hand-written, no spam. Unsubscribe in one click.