diff --git a/src/tagged-union.ts b/src/tagged-union.ts index da2245e..3071b45 100644 --- a/src/tagged-union.ts +++ b/src/tagged-union.ts @@ -1,4 +1,4 @@ -import type { Exact, ValueOf } from "type-fest"; +import type { Exact, UnknownRecord, ValueOf } from "type-fest"; type UnaryFn = (shape: T) => R; @@ -98,27 +98,26 @@ interface TaggedUnionMatcherWidening { type HandlerMap = Record | undefined>; -// `object` carries no index signature, so the read needs the assertion; the -// factory admits only keys whose values are `string | number` tags, so the -// result is narrowed to the map's key space. -const tagAt = (shape: object, k: PropertyKey): string | number => - // oxlint-disable-next-line typescript/no-unsafe-type-assertion - (shape as Record)[k] as string | number; - const dispatch = (k: PropertyKey) => (handlers: HandlerMap, fallback?: UnaryFn) => - (shape: object): unknown => - ( - handlers[tagAt(shape, k)] ?? + (shape: object): unknown => { + // `object` carries no index signature, so the read needs the assertion; + // the factory admits only keys whose values are `string | number` tags, + // so the result is narrowed to the map's key space. + // oxlint-disable-next-line typescript/no-unsafe-type-assertion + const tag = (shape as UnknownRecord)[k] as string | number; + return ( + handlers[tag] ?? fallback ?? (() => { - throw new Error(`Unhandled tag: ${String(tagAt(shape, k))}`); + throw new Error(`Unhandled tag: ${String(tag)}`); }) )( // oxlint-disable-next-line typescript/no-unsafe-type-assertion shape as never, ); + }; export const getTaggedUnionMatcher = () =>