Loading docs…
Loading docs…
Creates an exhaustive guard for a union with a shared literal discriminant. The guard selects a branch from the input's discriminant value, then delegates to that branch guard.
For open inputs, discriminatedUnionWithFallback classifies undeclared discriminants into one explicit, canonical fallback variant. Its fallback tag must have a distinct runtime key from the known branch values, so 1 also reserves '1'. The fallback factory creates a plain-record payload for that variant or returns undefined to mark the input invalid; malformed known branches, non-plain payloads, and payloads with custom prototypes, accessor fields, or function fields never produce a fallback. Payload types must have a finite property shape, not a broad or patterned index signature. The classifier returns the standard tagged parse result.
The value tuple and branch map must each contain every discriminant value. Pair it with typedStruct to check each branch's fields against its existing TypeScript type.
The discriminant must be a required finite literal string, number, symbol, or boolean property on every union member. Broad string, number, and symbol values are rejected because a branch map cannot represent them exhaustively. Infinite template-literal types are rejected for the same reason. Boolean branches use true and false object keys, which makes ok-based Result types a natural fit.
Discriminants that coerce to the same object key, such as 1 and '1', are rejected because a branch map cannot represent them separately.
For a __proto__ discriminant, use the computed key ['__proto__'] (or a null-prototype map). An uncomputed object-literal key changes the map's prototype instead of creating a branch entry.
import {discriminatedUnion,isNumber,oneOfValues,typedStruct,} from 'is-kit';type Event =| { kind: 'click'; x: number; y: number }| { kind: 'scroll'; delta: number };const eventUnion = discriminatedUnion<Event>();export const isEvent = eventUnion('kind', ['click', 'scroll'], {click: typedStruct<Extract<Event, { kind: 'click' }>>()({kind: oneOfValues('click'),x: isNumber,y: isNumber,}),scroll: typedStruct<Extract<Event, { kind: 'scroll' }>>()({kind: oneOfValues('scroll'),delta: isNumber,}),});isEvent({ kind: 'click', x: 12, y: 24 }); // trueisEvent({ kind: 'hover', target: 'button' }); // false// TypeScript error: the scroll branch is required.eventUnion('kind', ['click', 'scroll'], {click: typedStruct<Extract<Event, { kind: 'click' }>>()({kind: oneOfValues('click'),x: isNumber,y: isNumber,}),});