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
- Change typescript target to es2020 In favor of https://github.com/kulshekhar/ts-jest/issues/1283 — committed to dooboolab-community/hackatalk by hyochan 4 years ago
- Change target to es2019 Without this change the nullish operator cannot be used. See https://github.com/kulshekhar/ts-jest/issues/1283#issuecomment-574261889 for details. — committed to serlo/cloudflare-worker by kulla 4 years ago
- Fix babel and jest By suggestion in https://github.com/kulshekhar/ts-jest/issues/1283#issuecomment-552147794 — committed to baruchiro/israeli-bank-scrapers by baruchiro 3 years ago
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:
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-jestthat you are usingbabelin 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
targettoES2015-ES2020as @squalsoft mentioned above, but whyESNEXTdoesn’t work?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.jsonhastarget: esnextor similar, try specify a lower ES version like https://kulshekhar.github.io/ts-jest/user/config/tsConfig .Thanks @squalsoft. Fixed my issue. FWIW
ES2020also works butESNEXTdoes 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.
I solved this using
ts-nodeby changing from Node v12 to v14.nvm use 14yes, you can either set to
truewhich will tellts-jestlook for default location, or you can specify the path to babel config. You can find here the documentationhttps://stackoverflow.com/questions/58725711/how-to-get-optional-chaining-working-in-typescript
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
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.