Stack Builders News

A collection of thoughts and notes by our team

Rayner Pupo

TypeScript definition improvements for RamdaJS


Today we are proud to present a small fix to the RamdaJS TypeScript definitions. The change itself fixed the type signature for the invoker function in the popular RamdaJS library. This issue prevented TypeScript users from correctly using the typings while calling the mentioned function.

We think that all developers should contribute to open source, and making fixes to the "typings" so that a JavaScript library can be more easily used in TypeScript is a great place to start! If you haven't made a contribution to open source before, this technical post will give you an idea of how to get involved.

  • Arity: The number of arguments that the function takes.
  • Currying: Breaking down a function with multiple arguments into a function that accepts only one argument at a time and returns a function that accepts the next parameter and so forth i.e fn(a, b, c) --> fn(a)(b)(c).
  • Rest parameters: Allows to pass several parameters that will be treated as an array within the function.
  • Side effects: When a function modifies some state outside its scope.

RamdaJS

RamdaJS brings certain features of functional programming into programs written in JavasScript. It contains a set of functions that encourage immutability and overall makes programmer life easier.

The Problem

According to the documentation, the function invoker in RamdaJS does the following:

Turns a named method with a specified arity into a function that can be called directly supplied with arguments and a target object. The returned function is curried and accepts arity + 1 parameters where the final parameter is the target object.

The old TypeScript definitions for the invoker function no longer match the above description or its plain JavaScript definition.

invoker(name: string, obj: any, len?: number): Function;
invoker(name: string): (obj: any, len?: number) => Function;

The Solution

The updated definition only requires the following signature:

invoker(arity: number, method: string): (...a: any[]) => any;

Let’s say we need to apply some arguments to an object function for example the slice from the string primitive data type.

The call would be like:

'abcdefg'.slice(3, 5); // 'de'

Then by using the RamdaJS invoker it would be like:

R.invoker(2, 'slice')(3, 5, 'abcdefg'); // 'de'

In this case we used an arity of 2 but the slice function also can be called with only one argument:

R.invoker(1, 'slice')(3, 'abcdefg'); // 'defg'

RamdaJS also applies some curry on the generated function so, calling:

R.invoker(2, 'slice')(3)(5, 'abcdefg'); // 'de'

Will produce the same result as the first example.

These kind of fixes are an ongoing process for TypeScript developers, given that JavaScript library developers don't always maintain the typings for TypeScript. Because of this, from time to time you may find that the function signatures are out of sync. We encourage readers to contribute to the TypeScript ecosystem by fixing mismatching type definitions since there are plenty of issues opened, and they can be easily fixed in most cases.

Do You Have What it Takes To Be a Stack Builder?