declare const corrupt: (unreachable: never) => never; type NoInfer = [T][T extends any ? 0 : never]; /** * `unknown` extends `any` will be true, * whereas `unknown` extends other types will be false */ type ValidateOutput = unknown extends T ? unknown : T; type ExhaustiveUnion = [ Union ] extends [string] ? { [Key in Union]: (value: Key) => Output; } & ExhaustiveDefaultCase> : Union extends boolean ? { true: (value: true) => Output; false: (value: false) => Output; } & ExhaustiveDefaultCase> : never; type ExhaustiveTag = [ Union[Tag] ] extends [string] ? { [Key in `${Union[Tag]}`]: (value: Extract) => Output; } & ExhaustiveDefaultCase> : Union[Tag] extends boolean ? { true: (value: Extract) => Output; false: (value: Extract) => Output; } & ExhaustiveDefaultCase> : never; type ExhaustiveDefaultCase = { /** * Default case * * @description * When declared, "exhaustive" will fallback to this case * instead of throwing an unreachable error on unmatched case */ _?: (value: never) => Output; }; /** * Ensures no extra values are passed to the object */ type ValidateKeys = [ keyof T ] extends [keyof U] ? T : { [Key in keyof U]: Key extends keyof T ? T[Key] : never; }; type MatchCases = unknown extends Output ? InferredCases : StrictCases; type ExtractOutput unknown>, Output> = unknown extends Output ? ValidateOutput> : Output; declare function exhaustive = ExhaustiveUnion>(union: Union, match: MatchCases>, ExhaustiveUnion, Output>): ExtractOutput; declare function exhaustive = ExhaustiveTag>(union: Union, tag: Tag, match: MatchCases>, ExhaustiveTag, Output>): ExtractOutput; declare namespace exhaustive { var tag: = ExhaustiveTag>(union: Union, tag: Tag, cases: MatchCases>, ExhaustiveTag, Output>) => ExtractOutput; } export { type ExhaustiveTag, type ExhaustiveUnion, corrupt, exhaustive };