Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

try to simplify esmock.d.ts types file #163

Merged
merged 5 commits into from
Sep 25, 2022

Conversation

iambumblehead
Copy link
Owner

@iambumblehead iambumblehead commented Sep 24, 2022

esmock.d.ts basically repeats the same definitions many times, because esmock's main function signature is exported in ways that are foreign to typescript. The various main esmock calls are shown below and they all have the same signature,

import esmock, { strict } from 'esmock'

const moduleId = './example.js';
const parent = import.meta.url
const mocks = {}
const globalmocks = {}
const opts = {}

esmock(moduleId, mocks, globalmocks, opts)
esmock(moduleId, parent, mocks, globalmocks, opts)
esmock.p(moduleId, mocks, globalmocks, opts) // persist cache
esmock.p(moduleId, parent, mocks, globalmocks, opts)
strict(moduleId, mocks, globalmocks, opts)
strict(moduleId, parent, mocks, globalmocks, opts)
strict.p(moduleId, mocks, globalmocks, opts) // persist cache
strict.p(moduleId, parent, mocks, globalmocks, opts)
esmock.strict(moduleId, mocks, globalmocks, opts)
esmock.strict(moduleId, parent, mocks, globalmocks, opts)
esmock.strict.p(moduleId, mocks, globalmocks, opts) // persist cache
esmock.strict.p(moduleId, parent, mocks, globalmocks, opts)

Searching for a way to re-use one documentation block and/or one esmock function signature, these attempts failed...

  • attempted to use the inheritdoc tag, but vscode did not show documentation for functions using inheritdoc,
  • attempted to define esmock function "types", then define those inside an esmock interface (rather than namespace) this didn't work and anyway was unable to export esmock as a "union" of esmock function and esmock interface

@iambumblehead
Copy link
Owner Author

@jsejcksn feel free to ignore me, but would give your experienced opinion on this types file? I experimented with some things from your answer here https://stackoverflow.com/questions/70629311/export-same-function-with-different-names-and-types but did not succeed and that's how I found you :)

@iambumblehead
Copy link
Owner Author

let's merge this... this esmock.d.ts file smaller and results seem acceptable in vscode

@iambumblehead iambumblehead merged commit b7b908f into master Sep 25, 2022
@iambumblehead iambumblehead deleted the try-to-simplify-d.ts-types-file branch September 25, 2022 04:49
@jsejcksn
Copy link
Contributor

@iambumblehead Hello. I'm just seeing this.

Would you give your opinion?
I experimented with some things ... but did not succeed

I'm not familiar with your codebase (and it looks like you might have already resolved whatever issue you encountered since this was merged), but do you have a specific question at this point?

@iambumblehead
Copy link
Owner Author

@jsejcksn thank you for your response. I don't understand typescript well but believed there might be a more compact way to format this types file, so I messaged you to ask for your general advice --is there a better way to write this types file?

You might, I thought, recommend a way to reuse function declarations or documentation tags here, but it seems typescript does not support these features, and the same declarations and tags are currently typed out for each function.

Copy link
Contributor

@jsejcksn jsejcksn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iambumblehead You seem to be asking about JSDoc, which is an entirely separate specification from TypeScript. However, TypeScript does support a subset of JSDoc's syntax.

Again, I haven't reviewed your codebase, but perhaps you're looking for something like this?

TS Playground

type MockMap = { [specifier: string]: any };

type Options = {
  strict?: boolean | undefined;
  purge?: boolean | undefined;
  isModuleNotFoundError?: boolean | undefined;
};

/**
 * Mocks imports for the module specified by {@link modulePath}.
 *
 * @param modulePath The module whose imports will be mocked.
 *
 * @param parent A URL used to resolve relative specifiers, typically
 * `import.meta.url`. If not specified, inferred via the stack. Useful with
 * source maps.
 *
 * @param defs A mapping of import specifiers to mock definitions.
 *
 * @param gdefs A globally applied mapping of import specifiers to mock
 * definitions.
 *
 * @param opts
 *
 * @returns The result of importing {@link modulePath}, similar to
 * `import(modulePath)`.
 */
type MockFunction = {
  (
    modulePath: string,
    parent: string,
    defs?: MockMap,
    gdefs?: MockMap,
    opts?: Options,
  ): any;
  (
    modulePath: string,
    defs?: MockMap,
    gdefs?: MockMap,
    opts?: Options,
  ): any;
};

/**
 * By default, mock definitions are merged with the original module definitions.
 * To avoid the default behaviour, use esmock.strict.
 */
declare const esmock: MockFunction & {
  /**
   * Uses caching to support `await import()` inside the mocked import tree.
   *
   * After using this function, consider calling {@link esmock.purge}
   * to free memory.
   */
  p: MockFunction;

  /**
   * Removes caching created by {@link esmock.p}.
   *
   * @param mockModule A module object returned from {@link esmock.p}.
   */
  purge: (mockModule: any) => void;

  /**
   * The "strict" variant replaces original module definitions
   * with mock definitions.
   */
  strict: MockFunction & {
    p: MockFunction;
  };
};

/**
 * The "strict" variant replaces original module definitions
 * with mock definitions.
 */
declare const strict: typeof esmock['strict'];

export {
  esmock as default,
  strict,
  type MockFunction,
  type MockMap,
  type Options,
};

@iambumblehead
Copy link
Owner Author

@jsejcksn wow your version looks amazing

All tests pass and here are screenshots from vscode

I'm not sure how to make the param docs appear in vscode, such as @param gdefs A globally applied mapping of import specifiers to mock but probably I am just unfamiliar with typescript.

The smaller adjustments and edits you made are also great. Thank you.

If you would make a PR I would be glad to merge it :)

@jsejcksn
Copy link
Contributor

I'm not sure how to make the param docs appear in vscode

@iambumblehead I'm not positive either and would need to experiment more: IntelliSense is what provides those quick info suggestions: that's also discrete from the TypeScript compiler.

You might check out the JSDoc @see directive (JSDoc, TS).

If you would make a PR I would be glad to merge it :)

PR created: #164

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants