jest-extended: Typescript error when importing jest-extended

Bug

jest-extended version: 1.0.0

.ts file:

import * as matchers from "jest-extended";

I get error: File ‘…/node_modules/jest-extended/types/index.d.ts’ is not a module.

Also, after upgrading to 1.0.0 unassigned import does not work any more:

import "jest-extended";

So: Unassigned import stoped working in version 1.0.0 And wildcard import does not work in typescript because of invalid .d.ts file.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 32
  • Comments: 55 (13 by maintainers)

Most upvoted comments

Had the same issue here when migrating to (ts-)jest 27 and jext-extended 1.0.0.

Before

I have in global.d.ts :

import 'jest-extended';

In jest.config.ts :

/* ... */
setupFilesAfterEnv: ['jest-extended'],
/* ... */

After

I just changed my jest.config.ts and add /all :

/* ... */
setupFilesAfterEnv: ['jest-extended/all'],
/* ... */

Everything seems to work fine with this change, like @silverwind pointed.

This was my fix:

// tsconfig.json (note that this shouldn't also be your build config)
  "include": [
    ...,
    "setupTestsAfterEnv.ts"
  ],
// jest.config.js
{
  ...,
  setupFilesAfterEnv: ['./setupTestsAfterEnv.ts'],
}
// setupTestsAfterEnv.ts

// import main for types & /all for matcher auto-registration
import 'jest-extended';
import 'jest-extended/all';

Importing jest-extended is all TS needs to get it to register the types, and you only have to import it once in your project. This does not however cause anything JS-related to actually happen, and you can’t really work with the exports of jest-extended because they aren’t in the type defs.

Importing jest-extended/all causes the auto-registration of all of the matchers, but doesn’t do anything types-wise. TS will allow un-typed imports like that though, since the side-effects aren’t modeled in TS’s type system.

A bit of bummer to need the two imports, but it’s easier than other solutions.

Updated solution, removes need for setupTests.ts:

With this configuration: I have intellisense in vscode, jest tests run as expected, and there’s no extra duplication, extra files, or //@ts-ignore

jest.config.js:

{
    // ...
    setupFilesAfterEnv: ['jest-extended/all']
}

./tsconfig.json:

{
    // ...
    "files": ["node_modules/jest-extended/types/index.d.s"]
}

I was caught out by this too. I previous had this at the top of each file that used jest-extended:

import "jest-extended";

To get things working again with v1.0.0 I removed all these imports and now have:

In setupTests.ts (called by setupFilesAfterEnv config):

import "jest-extended/all";

In global.d.ts:

/// <reference types="jest-extended" />

Now everything is working again properly and it’s simpler as jest-extended doesn’t need to be imported all over the place.

I have the same issue too. My tests used to run fine when doing:

import "jest-extended"

But after updating to v1.0.0, every function I used gives me the error such as:

expect(...).toBeEmpty is not a function".

I tried the full typescript setup as documented (using global.d.ts, include), but did not help.

Hey all I’ve just opened #407 with an example project that demos how to setup jest-extended globally with Typescript.

Please let me know if this resolves the issues.

Note: From what I can tell there is a separate issue / confusion around manually importing the matchers and the types lining up. I think it may be worth separating this into a different issue.

DO NOT USE @ts-ignore to squash the errors

This is an absolute last resort feature that undermines type-safety and will introduce more problems than fix. Most errors come from a flaw in the tsconfig.json configuration or a missing type from the @types/<pkg> or package.json[types] declaration files.

INSTEAD

A better solution for Typescript + ts-jest + jest-extended is detailed in this Gist. The Gist provides a description of how to configure types detection, associated project organization, and integration with ts-jest.

Separately, in contradiction to this repository’s README.md I do not recommend adding the jest-extended types reference to globals.d.ts with the rest of your project. This does not separate your tests from your source code and if you emit declaration files or other compiled files, it might include jest types. Additionally, if you happen to have a type that overlaps with jest-extended then your Typescript will not warn you that your type is not declared when it really references a jest-extended type. Instead, you should create a tsconfig.jest.json extension file specifically for ts-jest. This is similar to the extension files used for eslint, when you want to lint your test files but they are not included in your src directory. See more details in the gist.

Screen Shot 2021-10-29 at 23 22 49

My workaround for this is as follows:

in setupTests.ts

// @ts-ignore
import matchers from 'jest-extended/all'
expect.extend(matchers)

Because typescript can’t find definitions, it will complain about every use of the new jest-extended methods. To override this behaviour in the tsc compiler, we have to add a // @ts-ignore comment above each line of code implementing on of thises methods

In my tests that use a jest-extended matcher method:

// @ts-ignore
expect(res.body).toContainKey('users')
// @ts-ignore
expect(res.body.users[0]).toContainKeys(['_id', 'name', 'email', 'role', 'createdAt'])

I’m hoping that this gets fixed in this awesome-looking library in the next version, shouldn’t be too difficult

May be related to https://github.com/jest-community/jest-extended/commit/a2904bd6b9d1ec215fcf006b00788ea90cf561bf which includes a breaking change when setupFilesAfterEnv is used. I had to add this /all suffix to get the matchers defined again.

@mattphillips yes, in what world do you think that will work with @jest/globals? the use case for which is to import the globals into your test file.

import { beforeEach, describe, expect, jest, test } from '@jest/globals'

@codejedi365 Good callout on the distribution config, as ours is not standard:

  • tsconfig.json for dev work like type-checking tests/etc and integrating with IDEs (via default file-naming convention)
  • tsconfig.build.json which extends tsconfig.json but excludes tests/etc (which doesn’t need filename convention because this is only used by builders for which it is easier to set the config path)

We also use babel for actual compilation (beyond type generation), so there’s a lot of custom stuff going on that I should’ve specified. But it was late and I’d spent a bunch of time trying other fixes in the package to see if there was an easy PR; those all would’ve required a similar setup or restructuring of the package (TS does not make it easy to type raw imports without resorting to relying on have adjacent type files). But I updated my example above with a note.

As far as what actually imports the types, it is definitely the import 'jest-extended' line (commenting that out gives me type errors again). It is technically a combination of doing that import in a file that TS is aware via the include, but without an import TS won’t ever load the types for the library (we do the same thing for jest-enzyme as well, though its main import auto-executes).

not a problem, @replete, thanks for the compliment. My apologies as it seems I came “off the top rope” on your comment. I was trying to make a point for all others in the channel but I don’t think it came off that way as I re-read. My apologies.

Yes, @ts-ignore is a quick fix when you don’t know what to do and it’s easy to feel that way when jumping into Typescript. I remember it was about a year ago today when I first started TS. Recommend read, read, and read all the theory behind it (Medium.com has some helpful articles) and keep tinkering with it until you find how to make the compiler happy and work for you.

I’m hoping my Gist post does solve the most of the issues here, I was thankful it worked after hours of messing with it. I think the complexity of Typescript configurations is most to blame and the unknown need of all of us to update our jest config to the new naming convention used by this library. If there is a root issue that needs fixing, I might have time in a few weeks.

here is a fix for that specific missing type

My work around: jest.config.js:

{ ...
  setupFilesAfterEnv: ['jest-extended/all']
...}

then created a new file called types/global.d.ts and put import 'jest-extended' into it then added it to the tsconfig file:

...
  "files": ["types/global.d.ts"],
...

Now typescript/vscode can find the types for intellisense.

@ilyub Does the solution in comment above solve your problem?

Missing functions might just be misses in the type file (https://github.com/jest-community/jest-extended/blob/main/types/index.d.ts). Please send PRs for any missing! 🙂

We should have tests for the types so we’re sure we don’t miss any…