OverloadBuilder
type Func = (..._) => any
const overload = <Default extends Func>(defaultFunc: Default): OverloadBuilder<Default> => {
// @ts-ignore
const match = cases => Object.assign(
(...args) => {
const matcher = cases.find(([ guard ]) => guard(args))
const func = matcher
? matcher[1]
: defaultFunc
return func(...args)
},
{ case: (matcher, handler) =>
match([ ...cases, [ matcher, handler ] ])
}
)
return match([]) as any
}
type OverloadBuilder<Default extends Func> = Default & {
case<Overload extends Func>(
guard: (args: any) => args is Parameters<Overload>,
handler: Overload
): OverloadBuilder<Default & Overload>
}