Skip to content

Guide to Typing ramda Functions

Harris Miller edited this page Jul 26, 2023 · 2 revisions

When passing an overloaded function into another function, typescript takes the last definition (see here). This means the most common definition should come last, eg

export function filter<T, P extends T>(pred: (val: T) => boolean): {
  (dict: Record<string, T>): Record<string, P>
  (list: readonly T[]): P[];
};

// if `(dict: Record<string, T>): Record<string, P>` was last,
// then `filter` would be expecting `Record<string, T>` as the argument and this function would fail
const pickFooAndFilter = pipe(prop('foo'), filter(isNotNil));

Additionally, the __: Placeholder argument must come first for overloads. It is important when that argument is just T, which is any. This is because __: Placeholder fulfills that generic, and you'll be in wrong overload when you pass it __.

// if you ordered it this way
export function assoc<T, K extends keyof U, U>(prop: K, val: T, obj: U): { /* ... */ }
export function assoc<K extends keyof U, U>(prop: K, __: Placeholder, obj: U): { /* ... */ }


// you'll end up with the wrong operation
const setFoo = assoc('foo', __, obj);
// would try to `obj['foo'] = __` instead of returning `(val: T) => O`
Clone this wiki locally