Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate JSDoc for `pipe`d ES6 function

I have a ES6-style function that is defined using function composition with asyncPipe.

import { getItemAsync } from 'expo-secure-store';

const asyncPipe = (...fns) => x => fns.reduce(async (y, f) => f(await y), x);

const getToken = () => getItemAsync('token');

const liftedGetToken = async ({ ...rest }) => ({
  token: await getToken(),
  ...rest,
});

const liftedFetch = ({ body, route, token, method = 'GET' } = {}) =>
  fetch(route, {
    ...(body && { body: JSON.stringify(body) }),
    headers: {
      'Content-Type': 'application/json',
      ...(token && { Authorization: `Bearer ${token}` }),
    },
    method,
  });

const json = res => res.json();

/**
 * @method
 * @param {Object} fetchSettings the settings for the fetch request
 * @param {Object} fetchSettings.body the body of the request
 * @param {string} fetchSettings.route the URL of the request
 * @param {string} fetchSettings.method the method of the request
 * @param {string} fetchSettings.token should only be used for testing and unauthenticated requests
 */
const request = asyncPipe(liftedGetToken, liftedFetch, json);

As you can see I tried adding a JSDoc description to it. But when I use it anywhere my editor, VSCode, doesn't suggest its parameters. How do you declare these kinds of functions with JSDoc? And how do I get params for this function to work with Intellisense?

like image 494
J. Hesters Avatar asked Oct 12 '19 07:10

J. Hesters


2 Answers

VSCode will try to display the comment of the anonymous function inside asyncPipe. If you add a JSDoc comment inside it you can see the behaviour:

const asyncPipe = (...fns) =>
  /**
   * My asyncPipe description
   * @param {Object} x Any object
   */
  x => fns.reduce(async (y, f) => f(await y), x);

const request = asyncPipe(liftedGetToken, liftedFetch, json);

example

Unfortunately there is no way in JSDoc to override the documentation of the anonymous function like you were trying to do. You could however force your intent to VSCode like this, do note that this introduces an extra function call:

const doRequest = asyncPipe(liftedGetToken, liftedFetch, json);

/**
 * @method
 * @param {Object} fetchSettings the settings for the fetch request
 * @param {Object} fetchSettings.body the body of the request
 * @param {string} fetchSettings.route the URL of the request
 * @param {string} fetchSettings.method the method of the request
 * @param {string} fetchSettings.token should only be used for testing and unauthenticated requests
 */
const request = fetchSettings => doRequest(fetchSettings);

solution example

like image 88
A1rPun Avatar answered Oct 11 '22 18:10

A1rPun


VSCode uses the TypeScript engine under the hood, which is not good at inferring types from function compositions, and as you've seen, does not recognize a point-free composition as a function declaration.

If you want type hints, you can specify the arguments to the composed function by wrapping a pointed function around it.

I'd write it something like this - note: default values make the JSDoc unnecessary for type hints, but you may want to keep the JSDoc for the descriptions, anyway. Also make sure that failures caused by default value fallbacks produce adequate error messaging.

/**
  * http request with JSON parsing and token management.
  * @param {Object} fetchSettings the settings for the fetch request
  * @param {Object} fetchSettings.body the body of the request
  * @param {string} fetchSettings.route the URL of the request
  * @param {string} fetchSettings.method the method of the request
  * @param {string} fetchSettings.token should only be used for testing and unauthenticated requests
  */
const request = ({
  body = {},
  route = '',
  method = 'GET',
  token = ''
}) => asyncPipe(liftedGetToken, liftedFetch, json)({
  body, route, method, token
});
like image 42
Eric Elliott Avatar answered Oct 11 '22 19:10

Eric Elliott