With JSDoc, how do I doc a param type to match a param used in a global method like fetch()?

Viewed 93

I'm writing some fetch interceptors in JavaScript. I've got a few functions that take the init object param from fetch (2nd arg) and return a modified version of it. Via JSDoc I want to note both the @param and @returns types should match the structure of the init param. How do I do this? And/or is this advisable?

Since I only modify a subset of the many properties of init I've also considered creating my own custom object type with just those properties referenced/modified. That might make sense-- init can have whatever props, but my method needs/cares only about these specific ones. But then, when I'm writing or adjusting the function itself, I'd like to know if I am incorrectly referring to a property that does not actually exist on init. So I think it makes sense in a way to have a full typeDef of this. But I welcome advice against this.

What I've tried: I've read that even with JavaScript, custom JavaScript types can be imported from typings files for various modules. I don't have experience with this. And in this case, fetch() is a W3C browser standard? so would there even be official typings for that somewhere on the interweb?

I've concocted something like this:

/**
 * Customize the config (init) for a fetch with our
 * own specific props
 *
 * @param {{manually list all props here? or create my own typeDef? Oh no }} config
 * @returns {ditto} new Config
 */
function getCustomConfig(config) {
//do something
return newConfig;
}

What's the best way to approach this?

EDIT UPDATE: As soon as I posted this I noticed that my IDE, VSCode recognizes a type called RequestInit. It comes from typescript/lib/lib.dom.d.ts and is defined as such:

interface RequestInit {
    /** A BodyInit object or null to set request's body. */
    body?: BodyInit | null;
    /** A string indicating how the request will interact with the browser's cache to set request's cache. */
    cache?: RequestCache;
    /** A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials. */
    credentials?: RequestCredentials;
    /** A Headers object, an object literal, or an array of two-item arrays to set request's headers. */
    headers?: HeadersInit;
    /** A cryptographic hash of the resource to be fetched by request. Sets request's integrity. */
    integrity?: string;
    /** A boolean to set request's keepalive. */
    keepalive?: boolean;
    /** A string to set request's method. */
    method?: string;
    /** A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode. */
    mode?: RequestMode;
    /** A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. */
    redirect?: RequestRedirect;
    /** A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer. */
    referrer?: string;
    /** A referrer policy to set request's referrerPolicy. */
    referrerPolicy?: ReferrerPolicy;
    /** An AbortSignal to set request's signal. */
    signal?: AbortSignal | null;
    /** Can only be null. Used to disassociate request from any Window. */
    window?: null;
}

Well then, this is what I want it seems. Apparently, VSCode has some magic to keep these types. But if I didn't have VSCode, where does this come from, is importing typescript itself enough to get this? And then, how would I know to look for RequestInit as the type I want, besides getting lucky here? Any advice on this is welcome as well as on the advisability of using this vs just referencing the few props I want.

1 Answers

To get a parameter type from a global function you can use typeof theGlobalFunction to get its type definition and extract the parameter with the utility type Parameters. For the fetch function it's going to be like the following:

/**
 * Customize the config (init) for a fetch with our
 * own specific props
 *
 * @param {Exclude<Parameters<typeof fetch>[0], URL>} config
 * @returns {Exclude<Parameters<typeof fetch>[0], URL>} new Config
 */
 function getCustomConfig(config) {
    //do something
    return newConfig;
}

Of course, for the fetch function there is no advantage as it's easier to use the public-defined parameter type RequestInfo as you've already discovered. So, just do this instead:

/**
 * Customize the config (init) for a fetch with our
 * own specific props
 *
 * @param {RequestInfo} config
 * @returns {RequestInfo} new Config
 */
 function getCustomConfig(config) {
    //do something
    return newConfig;
}
Related