import { arg, Call, Fn, PartialApply, unset } from "../../core/Core"; import { Primitive, UnionToIntersection } from "../../helpers"; type GetWithDefault = K extends keyof Obj ? Obj[K] : Def; type ReplaceArgsWithConstraint = pattern extends arg ? Constraint : pattern extends Primitive ? pattern : pattern extends [any, ...any] ? { [key in keyof pattern]: ReplaceArgsWithConstraint; } : pattern extends (infer V)[] ? ReplaceArgsWithConstraint[] : pattern extends object ? { [key in keyof pattern]: ReplaceArgsWithConstraint; } : pattern; type DoesMatch = value extends ReplaceArgsWithConstraint ? true : false; type ExtractArgObject = pattern extends arg ? { [K in N]: value; } : pattern extends [] ? {} : [value, pattern] extends [ [ infer valueFirst, ...infer valueRest ], [ infer patternFirst, ...infer patternRest ] ] ? ExtractArgObject & ExtractArgObject : [value, pattern] extends [(infer valueFirst)[], (infer patternFirst)[]] ? ExtractArgObject : [value, pattern] extends [object, object] ? UnionToIntersection<{ [k in keyof value & keyof pattern]: ExtractArgObject; }[keyof value & keyof pattern]> : {}; type WithDefaultArgs = [Args[number]] extends [unset] ? Def : Args; type ArgObjectToArgs = [ GetWithDefault, GetWithDefault, GetWithDefault, GetWithDefault ]; type ExtractArgs = WithDefaultArgs>, [ value ]>; export type Match[]> = patterns extends [ With, ...infer restPatterns extends With[] ] ? DoesMatch extends true ? handler extends Fn ? Call, ExtractArgs>> : handler : Match : never; export type With = { pattern: pattern; handler: handler; }; export {};