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?
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);
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);
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
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With