ts-jest: Syntax Error with Optional Chaining in Typescript 3.7

Issue :

I just upgraded a repo to use Typescript 3.7 to test out optional chaining. It compiles successfully (using webpack and @babel/preset-typescript). However when I run a test against the optional chaining syntax I get an error that Jest can’t parse it.

Expected behavior:

Test should pass as normal

Error output:

 ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    filename.tsx:30
        const isStoreOwner = () => user?.isStoreOwner;
                                        ^

    SyntaxError: Unexpected token .

Jest.config.js:

  verbose: true,
  testURL: "http://localhost/",
  transform: {
    "^.+\\.tsx?$": "ts-jest",
    "^.+\\.jsx?$": "babel-jest",
  },

  modulePathIgnorePatterns: ["<rootDir>/script/scaffold/", "<rootDir>/.*/__mocks__"],

  testRegex: "(/app/javascript/.*(test|spec))\\.(jsx?|tsx?)$",
  moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node", "d.ts"],

  snapshotSerializers: ["enzyme-to-json/serializer"],

  moduleNameMapper: {
    "^.+\\.(css|scss|sass|jpg|jpeg|png|gif)$": "<rootDir>/app/javascript/helpers/fileStub.ts",
    "\\.svg": "<rootDir>/__mocks__/svgr.tsx",
  },

  setupFilesAfterEnv: ["<rootDir>/app/javascript/testing/test-setup.ts"],

package.json:

    "@babel/core": "^7.7.0",
    "@babel/plugin-proposal-class-properties": "^7.7.0",
    "@babel/plugin-proposal-decorators": "^7.7.0",
    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
    "@babel/plugin-proposal-object-rest-spread": "^7.6.2",
    "@babel/plugin-proposal-optional-chaining": "^7.6.0",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@babel/preset-env": "^7.7.1",
    "@babel/preset-react": "^7.7.0",
    "@babel/preset-typescript": "^7.7.0",
    "@types/enzyme": "^3.10.3",
    "@types/enzyme-adapter-react-16": "^1.0.5",
    "@types/jest": "^24.0.21",
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.15.1",
    "enzyme-to-json": "^3.4.3",
    "fork-ts-checker-webpack-plugin": "^3.0.1",
    "jest": "^24.9.0",
    "ts-jest": "^24.1.0",
    "typescript": "^3.7.2",

I’m unsure which library is causing the error (ts-jest, jest, babel, etc) but this seemed like a good place to start.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 41
  • Comments: 36

Commits related to this issue

Most upvoted comments

Optional chaining was added in ES2020, which isn’t supported by node yet. So if your ‘target’ compile option is ES2020 or ESNext, then typescript compiler will see an optional chaining operator and leave it alone. If your target is ES2019 or further back then typescript will transpile the feature into something that ndoe will understand . like this:

const attributeScores = (_a = apiResponse === null || apiResponse === void 0 ? void 0 : apiResp…

I changed tsconfig.json to have “target”: “ES2019” and this fixed same issue.

hi @JoshRobertson , @ntucker , Please check my repo to see a working example with optional chaining. My guess is because you didn’t inform ts-jest that you are using babel in your project which leads to the error.

I do not use babel, and I have the same issue.

It indeed works when I change the target to ES2015 - ES2020as @squalsoft mentioned above, but why ESNEXT doesn’t work?

It compiles successfully (webpack

One important difference with Jest is, the transformed code have to be executed (thus, supported) by current node version (this not true when bundling them for browser).

If tsconfig.json has target: esnext or similar, try specify a lower ES version like https://kulshekhar.github.io/ts-jest/user/config/tsConfig .

Thanks @squalsoft. Fixed my issue. FWIW ES2020 also works but ESNEXT does not.

Same issue is fixed for me with upgrading all @babel/* dependencies (to version 7.8.3 currently). But presumably only latest version of @babel/preset-typescript is needed. image

I solved this using ts-node by changing from Node v12 to v14.

nvm use 14

yes, you can either set to true which will tell ts-jest look for default location, or you can specify the path to babel config. You can find here the documentation

Along with the solutions posted above, I had to move package.json configuration to separate jest.config.js file. Then it worked 😃 Maybe ts-jest can work with just separate jest config file?

Just to follow up, the reason my babel config was failing was

 ["@babel/preset-env", { modules: false, useBuiltIns: "entry", corejs: 3 }],

the modules:false (which is needed for tree shaking in webpack) was causing syntax errors on import statements. Fortunately, this can be removed in Babel 7 and webpack will handle enabling module transformation automatically, allowing Jest to use the Babel config as well.