Skip to content

Instantly share code, notes, and snippets.

@AlexFrazer
Created August 3, 2026 14:02
Show Gist options
  • Select an option

  • Save AlexFrazer/fdbb8e772bccc24955aefbfda8c08cfd to your computer and use it in GitHub Desktop.

Select an option

Save AlexFrazer/fdbb8e772bccc24955aefbfda8c08cfd to your computer and use it in GitHub Desktop.
if-else.ts
import { curry } from "lodash/fp";
type Predicate<T, U extends T> = (value: T) => value is U;
type Transform<T> = <R = unknown>(value: T) => R;
type BranchReturn<
T,
U extends T,
TBranch extends Transform<U>,
FBranch extends Transform<T>
> = T extends U ? ReturnType<TBranch> : ReturnType<FBranch>;
export interface IfElse {
// (predicate, onTrue, onFalse, data)
<T, U extends T, TBranch extends Transform<U>, FBranch extends Transform<T>>(
predicate: Predicate<T, U>,
onTrue: TBranch,
onFalse: FBranch,
data: T
): BranchReturn<T, U, TBranch, FBranch>;
// (predicate) => (onTrue, onFalse, data)
<T, U extends T>(predicate: Predicate<T, U>): <
TBranch extends Transform<U>,
FBranch extends Transform<T>
>(
onTrue: TBranch,
onFalse: FBranch,
data: T
) => BranchReturn<T, U, TBranch, FBranch>;
// (predicate, onTrue) => (onFalse, data)
<T, U extends T, TBranch extends Transform<U>>(
predicate: Predicate<T, U>,
onTrue: TBranch
): <FBranch extends Transform<T>>(
onFalse: FBranch,
data: T
) => BranchReturn<T, U, TBranch, FBranch>;
// (predicate, onTrue, onFalse) => (data)
<T, U extends T, TBranch extends Transform<U>, FBranch extends Transform<T>>(
predicate: Predicate<T, U>,
onTrue: TBranch,
onFalse: FBranch
): (data: T) => BranchReturn<T, U, TBranch, FBranch>;
// (predicate) => (onTrue) => (onFalse, data)
<T, U extends T>(predicate: Predicate<T, U>): <TBranch extends Transform<U>>(
onTrue: TBranch
) => <FBranch extends Transform<T>>(
onFalse: FBranch,
data: T
) => BranchReturn<T, U, TBranch, FBranch>;
// (predicate) => (onTrue, onFalse) => (data)
<T, U extends T>(predicate: Predicate<T, U>): <
TBranch extends Transform<U>,
FBranch extends Transform<T>
>(
onTrue: TBranch,
onFalse: FBranch
) => (data: T) => BranchReturn<T, U, TBranch, FBranch>;
// (predicate, onTrue) => (onFalse) => (data)
<T, U extends T, TBranch extends Transform<U>>(
predicate: Predicate<T, U>,
onTrue: TBranch
): <FBranch extends Transform<T>>(
onFalse: FBranch
) => (data: T) => BranchReturn<T, U, TBranch, FBranch>;
// (predicate) => (onTrue) => (onFalse) => (data)
<T, U extends T>(predicate: Predicate<T, U>): <TBranch extends Transform<U>>(
onTrue: TBranch
) => <FBranch extends Transform<T>>(
onFalse: FBranch
) => (data: T) => BranchReturn<T, U, TBranch, FBranch>;
}
const ifElse = curry(function ifElse<
T,
U extends T,
TBranch extends Transform<U>,
FBranch extends Transform<T>
>(predicate: Predicate<T, U>, onTrue: TBranch, onFalse: FBranch, data: T) {
return predicate(data) ? onTrue(data) : onFalse(data);
}) as IfElse;
export default ifElse;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment