My attempt to enhance the typing of ifElse in Ramda, which currently has a type definition as follows:
export function ifElse(fn: Pred, onTrue: Arity2Fn, onFalse: Arity2Fn): Arity2Fn;
However, I quickly reached the limitations of TypeScript (or rather my skills) when trying to make improvements:
type Pred = <T>(o: T) => boolean
type Branch = <T>(o: T) => any
type Prop = <T, K extends keyof T>(k: K) => (o: T) => T[K]
type IfElseBase = (p: Pred, t: Branch, f: Branch) => (obj: any) => any
type IfElse = IfElseBase extends (
(p: (obj: any) => infer RP, t: (obj: any) => infer RT, f: (obj: any) => infer RF) => (obj: infer OBJ) => any)
? (p: (o: OBJ) => RP, t: (o: OBJ) => RT, f: (o: OBJ) => RF) => (o: OBJ) => RP extends true ? RT : RF
: IfElseBase
// Code details omitted for brevity
Feel free to explore and experiment further with the code in this Playground