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

Ava test() expression is not callable / has no call signatures #2539

Closed
dcsan opened this issue Jul 14, 2020 · 16 comments · Fixed by #2836
Closed

Ava test() expression is not callable / has no call signatures #2539

dcsan opened this issue Jul 14, 2020 · 16 comments · Fixed by #2836
Assignees
Labels
blocked waiting on something else to be resolved first bug current functionality does not work as desired scope:typescript

Comments

@dcsan
Copy link

dcsan commented Jul 14, 2020

I ran npm ava init in a project and created a first test as per ava docs.

Immediately the vscode editor is giving me a typescript warning error.

This expression is not callable.
  Type 'typeof import("/Users/dc/dev/exiteer/xbot/server/node_modules/ava/index")' has no call signatures.

image

I did look if there were separate typings but there is a index.d.ts as part of the basic module that's installed.

We'll also need your AVA configuration (in package.json or ava.config.* configuration files) and how you're invoking AVA. Share the installed AVA version (get it by running npx ava --version).

At this point i don't have any config files for ava, the initial install didn't seem to create.

FWIW this is a js file but I am leaving the typescript error checking running, i find it catches a lot of type errors even in plain JS files without type declarations.

@dcsan dcsan changed the title has no call signatures Ava test() expression is not callable / has no call signatures Jul 14, 2020
@novemberborn
Copy link
Member

My guess is that this is a mis-match between the type definition using export default and the import here using require(). @sindresorhus what do you think?

In #2435 I'm switching to a CJS export, but that work's stalled. It'd be a breaking change I think.

@dcsan
Copy link
Author

dcsan commented Jul 15, 2020

I think it might be cos I was trying to switch over from Jest. I'm not clear exactly but i think Jest does various things to your env... injecting globals somehow? This was for a project based on a boilerplate I used.

there's a jest.config.js sitting there, but not sure how that would take control of my system 🗡️

perhaps a part at the end of the

.eslintrc.js

module.exports = {
  parser: 'babel-eslint',

  parserOptions: {
    ecmaVersion: 2018,
  },
  extends: ['eslint:recommended', 'prettier'],
  env: {
    node: true,
  },
  rules: {
    'prettier/prettier': [
      'error',
      {
        trailingComma: 'es5',
        singleQuote: true,
        semi: false,
      },
    ],
    semi: [2, 'never'],
  },
  plugins: ['prettier', 'babel'],
  overrides: [
    {
      files: ['**/*.test.js'],
      env: {
        jest: true,
      },
    },
  ],
}

@novemberborn
Copy link
Member

Oh right I thought this was some type output from VSCode but you're saying it's from ESLint?

@sindresorhus
Copy link
Member

My guess is that this is a mis-match between the type definition using export default and the import here using require(). @sindresorhus what do you think?

Correct. See: sindresorhus/memoize#31

@dcsan
Copy link
Author

dcsan commented Jul 15, 2020

Oh right I thought this was some type output from VSCode but you're saying it's from ESLint?

The message is within VS code, but i think from the typescript compile checker ts in the error code.

ts2349 shows up this issue in the TS repo
microsoft/TypeScript#35423

and const assertion as a solution

@novemberborn novemberborn self-assigned this Jul 19, 2020
@novemberborn novemberborn added bug current functionality does not work as desired and removed needs triage labels Jul 19, 2020
@novemberborn novemberborn linked a pull request Jul 19, 2020 that will close this issue
@feljx
Copy link

feljx commented Sep 11, 2020

const test = require('ava').default
instead of
const test = require('ava')
fixes it!

@andria-dev
Copy link

@feljx's solution does seem to work. This should be the documented way of using AVA or we should find a way to fix this type definition issue.

I have found a solution to this. If we replace the following line in the index.d.ts file, everything works as expected; there are no issues and the type definitions work properly with a regular require.

// Replace this
export default test;

// With this
export = test;

However, I'm unaware of how AVA's type definition file was made — i.e. automated or hand-made. If it was hand-made, I or someone else can make a PR for this, which should be simple given it is only a one-line change. If the generation of index.d.ts is automated, perhaps we can open up an issue with the tool that generated invalid type definitions.

@novemberborn
Copy link
Member

AVA 4 (prereleases available) now ships with an ESM entrypoint that uses export default test, and a CJS entrypoint that module.exports = test. I'm hoping that the export default test type definition works for both, I'm really not sure whether you can have separate types for the different module systems.

@andria-dev
Copy link

andria-dev commented Apr 11, 2021

@novemberborn export default test in a type definition .d.ts only works for ESM imports but export = test will work for both. Could we revisit the idea of using export = test? You can test this by creating the following type definition files and doing both import and require.

// test.js
module.exports = function (name) {
  return;
}
// test.d.ts
declare function test(name: string): void;
export default test; // this looks valid but does not work with VSCode for require.
// index.js
import test1 from './test';
const test2 = require('./test'); // The type is "import test2" instead of the function declaration above.

test1("a");
test2("b"); // This expression is not callable

Now if you replace export default test in the above example with export = test the types work as expected. The below video shows this in action.

index.js.-.test.WSL_.Ubuntu.-.Visual.Studio.Code.2021-04-11.10-23-00.mp4

I also tested this with all plugins disabled in VSCode and it still happens. I also tried it with my TypeScript version set to typescript@latest.

@andria-dev
Copy link

And @novemberborn you can have different types for different module systems I believe. Each entry point needs its own .d.ts file anyway as far as I know. However, it would seem that it would be easier to use only export = test than maintain two different .d.ts files for the same source code.

@novemberborn
Copy link
Member

OK, I'll have a play with your examples and AVA itself. It's not something I've run into myself. Do you know if it's somehow related to the TypeScript config?

you can have different types for different module systems I believe.

AVA 4 uses Node.js exports mapping, so it's transparent to the consumer. Use require() and you get the CJS entry point, use import and you get the ESM one. I don't know if TypeScript resolves that. Sounds complicated.

@novemberborn novemberborn reopened this Apr 12, 2021
@andria-dev
Copy link

@novemberborn If you're referring to an individual project's TypeScript configuration, I don't think that is the issue because I didn't even have a TypeScript config for the above example. It could be related to how VSCode integrates with TypeScript for type checking related features perhaps, however, if that is the case, creating a fix in this repository would still benefit VSCode users while the upstream issue is being fixed.

@novemberborn
Copy link
Member

If you're referring to an individual project's TypeScript configuration, I don't think that is the issue because I didn't even have a TypeScript config for the above example.

That's a great clue 😄

@novemberborn novemberborn added this to the 4.0 milestone May 3, 2021
@novemberborn
Copy link
Member

@andria-dev I can definitely reproduce this, but I don't think there's a solution.

export = test should be used with import test = require('ava') which isn't great. You can't export any other types either.

With export default test and const test = require('ava') VSCode assumes the imported test is an object with a default property. However AVA correctly exports both an ESM and a CJS module, so this isn't the case.

I think we need TypeScript support for this, microsoft/TypeScript#33079 seems to be the relevant issue.

In the mean time, I'd rather stick to the ESM syntax.

@novemberborn novemberborn added the blocked waiting on something else to be resolved first label Jul 5, 2021
@novemberborn novemberborn removed this from the 4.0 milestone Jul 5, 2021
@novemberborn novemberborn removed their assignment Jul 5, 2021
@simonhaenisch
Copy link

How about also adding module.exports.test = test so that we can alternatively import it as a named import, i. e.

const { test } = require('ava');

?

novemberborn added a commit that referenced this issue Sep 18, 2021
Our type definition uses ESM syntax; when using CJS with VSCode, the
auto-completion assumes the root is accessed through `require('ava').default`.
Placate VSCode by adding a mostly hidden default property on the root. This is
available through both CJS and ESM imports. We use a proxy so that we don't end
up with root.default.default.default chains.

Fixes #2539.
@novemberborn
Copy link
Member

#2836 makes this work through require('ava').default.

@novemberborn novemberborn self-assigned this Sep 18, 2021
novemberborn added a commit that referenced this issue Sep 18, 2021
Our type definition uses ESM syntax; when using CJS with VSCode, the
auto-completion assumes the root is accessed through `require('ava').default`.
Placate VSCode by adding a mostly hidden default property on the root. This is
available through both CJS and ESM imports. We use a proxy so that we don't end
up with root.default.default.default chains.

Fixes #2539.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked waiting on something else to be resolved first bug current functionality does not work as desired scope:typescript
Projects
None yet
6 participants