{"id":15686232,"url":"https://github.com/sambacha/typescript-cjs-esm-tests","last_synced_at":"2026-02-03T08:03:09.655Z","repository":{"id":38022227,"uuid":"490975289","full_name":"sambacha/typescript-cjs-esm-tests","owner":"sambacha","description":"Fundamentals of ESM/CJS modules and their Heresies","archived":false,"fork":false,"pushed_at":"2025-08-07T09:45:28.000Z","size":325,"stargazers_count":10,"open_issues_count":4,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-11T01:57:36.412Z","etag":null,"topics":["cjs","docs","esm","module-resolution","modules","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sambacha.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-05-11T05:55:25.000Z","updated_at":"2025-08-07T09:44:20.000Z","dependencies_parsed_at":"2025-07-08T21:35:49.222Z","dependency_job_id":"8cf36a2e-1169-4227-885a-877d585e6af9","html_url":"https://github.com/sambacha/typescript-cjs-esm-tests","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/sambacha/typescript-cjs-esm-tests","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Ftypescript-cjs-esm-tests","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Ftypescript-cjs-esm-tests/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Ftypescript-cjs-esm-tests/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Ftypescript-cjs-esm-tests/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sambacha","download_url":"https://codeload.github.com/sambacha/typescript-cjs-esm-tests/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sambacha%2Ftypescript-cjs-esm-tests/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29037748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T06:39:36.383Z","status":"ssl_error","status_checked_at":"2026-02-03T06:39:32.787Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cjs","docs","esm","module-resolution","modules","typescript"],"created_at":"2024-10-03T17:36:35.906Z","updated_at":"2026-02-03T08:03:09.646Z","avatar_url":"https://github.com/sambacha.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fundementals of ESM/CJS modules and their Heresies\n\n\u003c!-- TOC start (generated with https://github.com/derlin/bitdowntoc) --\u003e\n\n- [`std.module.format` ](#stdmoduleformat)\n      + [Different Types of Imports and Exports](#different-types-of-imports-and-exports)\n   * [The Special Case of `export default`](#the-special-case-of-export-default)\n      + [Why the Difference?](#why-the-difference)\n   * [The Third Way: `export { thing as default }`](#the-third-way-export-thing-as-default-)\n      + [Special Case: `export default function`](#special-case-export-default-function)\n   * [Circular Dependencies and Hoisting](#circular-dependencies-and-hoisting)\n      + [Function Hoisting Behavior](#function-hoisting-behavior)\n      + [Circular Dependencies Example](#circular-dependencies-example)\n   * [Summary](#summary)\n   * [Why you may need to publish CJS to have ESM work](#why-you-may-need-to-publish-cjs-to-have-esm-work)\n   * [Usage](#usage)\n      + [Multiple Entries](#multiple-entries)\n      + [Custom Files](#custom-files)\n      + [Best Practices](#best-practices)\n         - [Named exports (blue boxes) create live references when imported through any import syntax](#named-exports-blue-boxes-create-live-references-when-imported-through-any-import-syntax)\n         - [Default exports (orange boxes) behave differently:](#default-exports-orange-boxes-behave-differently)\n         - [Circular dependencies behavior:](#circular-dependencies-behavior)\n      + [ES6 exports / imports cheat sheet](#es6-exports-imports-cheat-sheet)\n   * [`package.json` TLDR](#packagejson-tldr)\n   * [Problematic Settings](#problematic-settings)\n      + [~~Dont use `browser` field~~ Use `browser` specifically for CDN's, YMMV per module usage](#dont-use-browser-field-use-browser-specifically-for-cdns-ymmv-per-module-usage)\n      + [Restrictions on Import Assertions Under ](#restrictions-on-import-assertions-under)\n      + [dont use `preserveModules` ](#dont-use-preservemodules)\n      + [`moduleResolution` `NodeNext` only allows defined import paths ](#moduleresolution-nodenext-only-allows-defined-import-paths)\n         - [correct manifest](#correct-manifest)\n   * [`load-esm.{ts,mts}`](#load-esmtsmts)\n   * [Motivation](#motivation)\n      + [Opt in compiler options](#opt-in-compiler-options)\n      + [Solution](#solution)\n         - [Other Compiler Options Affecting the Build Result](#other-compiler-options-affecting-the-build-result)\n         - [Suggested `tsconfig` values](#suggested-tsconfig-values)\n   * [Side by Side Compare](#side-by-side-compare)\n      + [node:assert](#nodeassert)\n         - [Modern](#modern)\n         - [Legacy](#legacy)\n   * [TLDR](#tldr)\n      + [Cheatsheet](#cheatsheet)\n   * [Avoid Default Exports and Prefer Named Exports](#avoid-default-exports-and-prefer-named-exports)\n      + [Context](#context)\n      + [Summary](#summary-1)\n   * [Decision](#decision)\n      + [ECMAScript Module Support in Node.js](#ecmascript-module-support-in-nodejs)\n      + [`.mjs`, `.cjs`, == `.mts`, `.cts` \u0026\u0026 `.d.mts` and `.d.cts`.](#mjs-cjs-mts-cts-dmts-and-dcts)\n   * [Avoid Export Default](#avoid-export-default)\n      + [Poor Discoverability](#poor-discoverability)\n      + [Autocomplete](#autocomplete)\n      + [CommonJS interop](#commonjs-interop)\n      + [Typo Protection](#typo-protection)\n      + [TypeScript auto-import](#typescript-auto-import)\n      + [Re-exporting](#re-exporting)\n      + [Dynamic Imports](#dynamic-imports)\n      + [ES Module Interop](#es-module-interop)\n            * [Note](#note)\n      + [Needs two lines for non-class / non-function](#needs-two-lines-for-non-class-non-function)\n      + [React.js - Named Exports](#reactjs-named-exports)\n   * [{} type](#-type)\n      + [If you want a type that means \"empty object\"](#if-you-want-a-type-that-means-empty-object)\n      + [If you are using React, and you want to define `type Props = {}`.](#if-you-are-using-react-and-you-want-to-define-type-props-)\n      + [`GenericObject`](#genericobject)\n      + [Module-related host hooks](#module-related-host-hooks)\n   * [Customizing module resolution](#customizing-module-resolution)\n      + [parserOptions.moduleResolver](#parseroptionsmoduleresolver)\n   * [Fixing ES6 Import Syntax with `verbatimModuleSyntax` ](#fixing-es6-import-syntax-with-verbatimmodulesyntax)\n      + [Use require() instead of import](#use-require-instead-of-import)\n      + [Disable verbatimModuleSyntax](#disable-verbatimmodulesyntax)\n      + [Use a compatibility layer](#use-a-compatibility-layer)\n   * [License](#license)\n\n\u003c!-- TOC end --\u003e\n\n\u003ca name=\"stdmoduleformat\"\u003e\u003c/a\u003e\n# `std.module.format` \n\n\n\u003e [!NOTE]\n\u003e updated 2025/04/11\n\n### Different Types of Imports and Exports\n\n\u003e an overview of how different imports and exports behave\n\n```javascript\n// These give you a live reference:\nimport { thing } from './module.js';\nimport { thing as otherName } from './module.js';\nimport * as module from './module.js';\nconst module = await import('./module.js');\n\n// This assigns the current value:\nlet { thing } = await import('./module.js');\n```\n\n## The Special Case of `export default`\n\n The `export default` syntax has different semantics than named exports.\n\n```javascript\n// module.js\nlet thing = 'initial';\nexport { thing };\nexport default thing;\nsetTimeout(() =\u003e {\n  thing = 'changed';\n}, 500);\n```\n\n\u003e Export Default Behavior\n\n\n### Why the Difference?\n\nThe reason for this behavior is that `export default` allows exporting values directly:\n\n```javascript\nexport default 'hello!';  // This works\nexport { 'hello!' as thing };  // This doesn't work\n```\n\n## The Third Way: `export { thing as default }`\n\nThere's another way to export a default that behaves differently:\n\n```javascript\n// module.js\nlet thing = 'initial';\nexport { thing, thing as default };\nsetTimeout(() =\u003e {\n  thing = 'changed';\n}, 500);\n```\n\nThis method maintains the live reference, unlike `export default thing`.\n\n### Special Case: `export default function`\n\nFunctions get special treatment:\n\n```javascript\n// module.js\nexport default function thing() {}\nsetTimeout(() =\u003e {\n  thing = 'changed';\n}, 500);\n\n// main.js\nimport thing from './module.js';\nsetTimeout(() =\u003e {\n  console.log(thing); // \"changed\"\n}, 1000);\n```\n\n\u003e Function Export Behavior\n\n\n## Circular Dependencies and Hoisting\n\n### Function Hoisting Behavior\n\n```javascript\nthisWorks();  // This runs fine\nfunction thisWorks() {\n  console.log('yep, it does');\n}\n```\n\n\u003e [!NOTE]\n\u003e Function declarations are hoisted, but other declarations aren't:\n\n```javascript\nassignedFunction();  // Doesn't work\nnew SomeClass();    // Doesn't work\n\nconst assignedFunction = function() {\n  console.log('nope');\n};\nclass SomeClass {}\n```\n\n### Circular Dependencies Example\n\n```javascript\n// main.js\nimport { foo } from './module.js';\nfoo();\nexport function hello() {\n  console.log('hello');\n}\n```\n\n```javascript\n// module.js\nimport { hello } from './main.js';\nhello();\nexport function foo() {\n  console.log('foo');\n}\n```\n\nThis works due to hoisting. However, changing to arrow functions breaks it:\n\n```javascript\n// main.js\nimport { foo } from './module.js';\nfoo();\nexport const hello = () =\u003e console.log('hello');\n```\n\n```javascript\n// module.js\nimport { hello } from './main.js';\nhello();\nexport const foo = () =\u003e console.log('foo');\n```\n\n## Summary\n\nThe complete behavior overview:\n\n```javascript\n// Live references:\nimport { thing } from './module.js';\nimport { thing as otherName } from './module.js';\nimport * as module from './module.js';\nconst module = await import('./module.js');\n\n// Value copy:\nlet { thing } = await import('./module.js');\n\n// Live reference exports:\nexport { thing };\nexport { thing as otherName };\nexport { thing as default };\nexport default function thing() {}\n\n// Value exports:\nexport default thing;\nexport default 'hello!';\n```\n\n## Why you may need to publish CJS to have ESM work\n\n\u003e `cjyes` [![npm version](https://img.shields.io/npm/v/cjyes.svg)](https://www.npmjs.org/package/cjyes)\n\n\u003e source: \u003chttps://gist.github.com/developit/96de429483bb98927c7cd27c773b0fff\u003e\n\nIf you're publishing ES Modules, you need to also publish CommonJS versions of those modules.\n\nThis isn't to support old browsers or Node versions: even in Node 14, using `require()` to load a module won't work if it's only available as ESM.\n\n`cjyes` is the bare minimum fix for this problem. You write ES Modules and fill out a valid `package.json`, and it'll generate the corresponding CommonJS files pretty much instantly. `cjyes` takes up 500kb of disk space including its two dependencies.\n\n## Usage\n\nThe easiest way to use `cjyes` is to define [package exports](https://nodejs.org/api/esm.html#esm_conditional_exports) the way Node 13+ requires:\n\n```json\n{\n  \"main\": \"index.mjs\",\n  \"exports\": {\n    \"import\": \"./index.mjs\",\n    \"require\": \"./dist/index.cjs\"\n  },\n  \"scripts\": {\n    \"prepare\": \"cjyes\"\n  },\n  \"devDependencies\": {\n\t\"cjyes\": \"^0.3.0\"\n  }\n}\n```\n\n`cjyes` will create CommonJS versions of all modules listed in the `\"exports\"` field and place them at the specified locations.\n\n\u003e You can also use `.js` file extensions and the `{\"type\":\"module\"}` field - cjyes will detect this and generate the required `.cjs` output files.\n\n### Multiple Entries\n\nMultiple entry points are supported automatically. Simply define them in your export map:\n\n```json\n{\n  \"main\": \"index.mjs\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./index.mjs\",\n      \"require\": \"./index.cjs\"\n\t},\n    \"./jsx\": {\n      \"import\": \"./jsx.mjs\",\n      \"require\": \"./jsx.cjs\"\n\t},\n    \"./hooks\": {\n      \"import\": \"./hooks/index.mjs\",\n      \"require\": \"./hooks/index.cjs\"\n\t}\n  },\n  \"scripts\": { \"prepare\": \"cjyes\" },\n  \"devDependencies\": { \"cjyes\": \"^0.3.0\" }\n}\n```\n\n### Custom Files\n\nIt is also possible to pass a list of input modules to `cjyes` directly:\n\n```sh\ncjyes src/index.js src/other.mjs\n# generates the following:\n# dist/\n#    index.cjs\n#    other.cjs\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e cjyes.js code\n\n\u003c/summary\u003e\n\n~~~javascript\n#! /usr/bin/env node\n\nconst path = require('path');\nconst fs = require('fs').promises;\nconst MagicString = require('magic-string').default;\nconst { parse } = require('es-module-lexer');\n\nconst ALIASES = {\n\t'-v': 'verbose',\n\t'-s': 'silent',\n\t'-d': 'dry'\n};\nconst FLAGS = {\n\tdefault: 'Force `exports.default=` instead of `module.exports=`',\n\tflat: 'Force merging named exports into default (module.exports=A;exports.B=B)',\n\tdry: `Don't write anything to disk [-d]`,\n\tverbose: 'Verbose output logging [-v]',\n\tsilent: 'No output logging [-s]'\n};\nrun(process.argv.slice(2))\n\t.then(() =\u003e process.exit(0))\n\t.catch(err =\u003e (console.error(err), process.exit(1)));\n\nasync function run(argv) {\n\tconst flags = {};\n\tconst files = argv.filter(file =\u003e {\n\t\treturn !((file in ALIASES || file.startsWith('--')) \u0026\u0026 (flags[ALIASES[file] || file.substring(2)] = true));\n\t});\n\tif (flags.help) return console.log(`cjyes [...files]\\nOptions:\\n    ${Object.keys(FLAGS).map(k=\u003e`--${k.padEnd(7)}  ${FLAGS[k]}`).join('\\n    ')}`);\n\tlet pkg;\n\ttry {\n\t\tpkg = JSON.parse(await fs.readFile('package.json','utf-8'));\n\t} catch (e) {}\n\tif (files.length === 0 \u0026\u0026 pkg \u0026\u0026 pkg.exports) {\n\t\tcrawl(pkg.exports, files);\n\t\tif (flags.verbose) {\n\t\t\tconsole.log(`[cjyes] Using files listing from Export Map:\\n  ${files.join('\\n  ')}`);\n\t\t}\n\t}\n\tconst ctx = {};\n\treturn Promise.all(files.map(f =\u003e cjs(f, { flags, pkg, ctx })))\n}\n\nasync function cjs(file, { flags, pkg, ctx }) {\n\tconst code = await fs.readFile(file, 'utf-8');\n\tconst out = new MagicString(code);\n\tconst [imports, exports] = await parse(code, file);\n\tfor (const imp of imports) {\n\t\tconst spec = JSON.stringify(code.substring(imp.s, imp.e));\n\t\tconst s = code.substring(imp.ss + 6, imp.s - 1).replace(/\\s*from\\s*/g, '');\n\t\tconst r = `const ${s.replace(/\\sas\\s/g, ':')} = require(${spec})`;\n\t\tout.overwrite(imp.ss, imp.se, r);\n\t}\n\tconst nonDefaultExports = exports.filter(p =\u003e p!=='default');\n\tconst defaultExport = !flags.flat \u0026\u0026 (flags.default || nonDefaultExports.length) ? 'exports.default=' : 'module.exports=';\n\tconst t = /(^|[;\\s(])export(\\s*default)?(?:\\s*{[^}]+}|\\s+(function|const|let|var))/g;\n\tlet token;\n\twhile ((token = t.exec(code))) {\n\t\tconst r = `${token[2] ? defaultExport : ''}${token[3] || ''}`;\n\t\tout.overwrite(token.index + token[1].length, t.lastIndex, r);\n\t}\n\tfor (const exp of nonDefaultExports) out.append(`\\nexports.${exp}=${exp};`);\n\n\tlet outFile;\n\t// use the export map if one exists:\n\tconst entry = './' + file.replace(/\\.m?js$/, '').split(path.sep).join('/');\n\tconst def = pkg \u0026\u0026 pkg.exports \u0026\u0026 resolve(pkg.exports, entry);\n\tif (def) {\n\t\tif (flags.verbose) {\n\t\t\tconsole.log(`[cjyes] using Export Map entry for ${entry}`);\n\t\t}\n\t\toutFile = def.replace(/^\\.\\//,'').split('/').join(path.sep);\n\t}\n\telse {\n\t\t// fall back to a dist directory\n\t\tconst ext = pkg \u0026\u0026 pkg.type === 'module' ? '.cjs' : '.js';\n\t\tconst parts = file.replace(/\\.m?js$/, ext).split(path.sep);\n\t\tconst index = parts.lastIndexOf('src');\n\t\tif (index === -1) parts.unshift('dist');\n\t\telse parts[index] = 'dist';\n\t\toutFile = parts.join(path.sep);\n\t\tif (!flags.silent \u0026\u0026 !ctx.warned) {\n\t\t\tctx.warned = true;\n\t\t\tconsole.log(`[cjyes] no Export Map found, generating filenames:`);\n\t\t\tif (ext=='.cjs') console.log(`  - Using .cjs due to {\"type\":\"module\"}`);\n\t\t\tif (index===-1) console.log(`  - Replacing src/ with dist/`);\n\t\t\telse console.log(`  - Prepending dist/ directory`);\n\t\t}\n\t}\n\tif (!flags.dry) {\n\t\ttry {\n\t\t\tawait fs.mkdir(path.dirname(outFile), { recursive: true });\n\t\t} catch (e) {}\n\t\tawait fs.writeFile(outFile, out.toString());\n\t}\n\tif (!flags.silent) {\n\t\tconsole.log(`${file} --\u003e ${outFile}`);\n\t}\n}\n\nfunction crawl(exp, files) {\n\tif (typeof exp==='string') files.push(exp.replace(/^\\.\\//,''));\n\telse if (exp.import || exp.default) crawl(exp.import || exp.default, files);\n\telse for (let i in exp) {\n\t\tif (i[0]=='.' \u0026\u0026 !i.endsWith('/')) crawl(exp[i], files);\n\t}\n}\n\nfunction resolve(exp, entry) {\n\tif (!exp || typeof exp=='string') return exp;\n\treturn exp.require || exp.default || resolve(select(exp, entry) || exp['.'], entry);\n}\n\nfunction select(exp, entry) {\n\tfor (let i in exp) if (i==entry) return exp[i];\n}\n~~~\n\n\u003c/details\u003e\n\n_Note: The original article was written by Jake Archibald, with contributions from the V8 team members Toon Verwaest, Marja Hölttä, and Mathias Bynens, as well as Dave Herman and Daniel Ehrenberg._\n\n### Best Practices\n\n1. Avoid circular dependencies whenever possible\n2. Be aware of the difference between value exports and reference exports\n3. Consider using `export { thing as default }` instead of `export default thing` when you need to maintain live bindings\n4. Remember that `export default function` is a special case that maintains references\n\n\n```mermaid\ngraph TD\n    subgraph \"Export Types\"\n        A[\"Named Export\u003cbr\u003eexport { thing }\"] --\u003e|\"Live Reference\"| D[\"Import { thing }\"]\n        A --\u003e|\"Live Reference\"| E[\"Import { thing as otherName }\"]\n        A --\u003e|\"Live Reference\"| F[\"Import * as module\"]\n        A --\u003e|\"Live Reference\"| G[\"await import('./module.js')\"]\n        \n        B[\"Default Export\u003cbr\u003eexport default thing\"] --\u003e|\"Value Copy\"| H[\"Import default\"]\n        \n        C[\"Function Export\u003cbr\u003eexport default function(){}\"] --\u003e|\"Live Reference\"| I[\"Import default function\"]\n        \n        J[\"Named as Default\u003cbr\u003eexport { thing as default }\"] --\u003e|\"Live Reference\"| K[\"Import default\"]\n    end\n    \n    subgraph \"Import Types\"\n        D\n        E\n        F\n        G --\u003e|\"Value Copy\"| L[\"let { thing } = await import()\"]\n        G --\u003e|\"Live Reference\"| M[\"const module = await import()\"]\n        H\n        I\n        K\n    end\n    \n    subgraph \"Circular Dependencies\"\n        N[\"Function Declaration\u003cbr\u003eexport function thing(){}\"] --\u003e|\"Works due to hoisting\"| O[\"Circular Import\"]\n        P[\"Arrow Function\u003cbr\u003eexport const thing = ()=\u003e{}\"] --\u003e|\"Fails - no hoisting\"| Q[\"Circular Import Fails\"]\n    end\n    \n    style A fill:#d4f1f9,stroke:#333\n    style B fill:#ffdfba,stroke:#333\n    style C fill:#ffdfba,stroke:#333,stroke-dasharray: 5 5\n    style J fill:#d4f1f9,stroke:#333,stroke-dasharray: 5 5\n    style N fill:#d8f8e1,stroke:#333\n    style P fill:#ffbaba,stroke:#333\n```\n\n#### Named exports (blue boxes) create live references when imported through any import syntax\n\nRegular named exports maintain live bindings to the original variables\nThe special export { thing as default } syntax also maintains live binding\n\n\n#### Default exports (orange boxes) behave differently:\n\nRegular export default thing creates a value copy (not a reference)\nThe special case export default function() {} maintains a live reference\n\n\n#### Circular dependencies behavior:\n\nFunction declarations (green box) work in circular dependencies due to hoisting\nArrow functions and const declarations (red box) fail in circular dependencies\n\n\u003ca name=\"es6-exports--imports-cheat-sheet\"\u003e\u003c/a\u003e\n### ES6 exports / imports cheat sheet\n\n\u003e https://github.com/eslint/espree/pull/43\n\u003e\n\n```javascript\n// default exports\nexport default 42;\nexport default {};\nexport default [];\nexport default (1 + 2);\nexport default foo;\nexport default function () {}\nexport default class {}\nexport default function foo () {}\nexport default class foo {}\n\n// variables exports\nexport var foo = 1;\nexport var foo = function () {};\nexport var bar;\nexport let foo = 2;\nexport let bar;\nexport const foo = 3;\nexport function foo () {}\nexport class foo {}\n\n// named exports\nexport {};\nexport {foo};\nexport {foo, bar};\nexport {foo as bar};\nexport {foo as default};\nexport {foo as default, bar};\n\n// exports from\nexport * from \"foo\";\nexport {} from \"foo\";\nexport {foo} from \"foo\";\nexport {foo, bar} from \"foo\";\nexport {foo as bar} from \"foo\";\nexport {foo as default} from \"foo\";\nexport {foo as default, bar} from \"foo\";\nexport {default} from \"foo\";\nexport {default as foo} from \"foo\";\nImport Syntax\n\n// default imports\nimport foo from \"foo\";\nimport {default as foo} from \"foo\";\n\n// named imports\nimport {} from \"foo\";\nimport {bar} from \"foo\";\nimport {bar, baz} from \"foo\";\nimport {bar as baz} from \"foo\";\nimport {bar as baz, xyz} from \"foo\";\n\n// glob imports\nimport * as foo from \"foo\";\n\n// mixing imports\nimport foo, {baz as xyz} from \"foo\";\nimport foo, * as bar from \"foo\";\n\n// just import\nimport \"foo\";\n```\n\n\u003ca name=\"packagejson-tldr\"\u003e\u003c/a\u003e\n## `package.json` TLDR\n\n```jsonc\n//...\n  \"type\": \"module\",\n  \"main\": \"dist/index.cjs\",   // or .js if \"type\" is unspecified\n  \"exports\": {\n    \"import\": \"./dist/index.js\",   // no need for .mjs if \"type\" is \"module\" (recommended)\n     \"require\": \"./dist/index.cjs\"   // or .js if \"type\" is unspecified\n//...\n```\n\n1. ESM resolution algorithm does not currently support automatic\nresolution of file extensions and does not have the hability to\nimport directories that have an index file. The extension and the name\nof the file being import need to _always_ be spcified. See:\nhttps://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm\n\n2. Typescript does not provide features that change compiled JS code.\nThis means there is no Typescript feature to include the \".js\" on\ncompiled code. See: microsoft/TypeScript#16577 (comment)\n\n\u003ca name=\"problematic-settings\"\u003e\u003c/a\u003e\n## Problematic Settings\n\n\u003e **Warning** \u003cbr /\u003e\n\u003e Use at your own discretion \n\n\u003ca name=\"dont-use-browser-field-use-browser-specifically-for-cdns\"\u003e\u003c/a\u003e\n### ~~Dont use `browser` field~~ Use `browser` specifically for CDN's, YMMV per module usage\n\njsdeliver cdn uses this see \u003chttps://github.com/jsdelivr/jsdelivr#configuring-a-default-file-in-packagejson\u003e\n\nwebpack's resolve module algorithm picks a more specific field from `package.json` (and other bundlers too), so webpack chooses UMD module from `browser` field on the default and that breaks tree-shaking[^1]\n\n[^1]: Source: https://github.com/TanStack/query/discussions/3986 - danke https://github.com/jeetiss\n\n\n\u003cdetails\u003e\n    \u003csummary\u003e@tanstack/query-example-react-nextjs\u003c/summary\u003e\n    \n\u003cimg width=\"1506\" src=\"https://user-images.githubusercontent.com/6726016/183033639-20b33c71-5c81-442c-a711-baa3b266f0dc.png\"\u003e\n\n\u003c/details\u003e\n\n\n\u003ca name=\"restrictions-on-import-assertions-under\"\u003e\u003c/a\u003e\n### Restrictions on Import Assertions Under \n\n\n```\n--module nodenext\n```\n\nImport assertions were a proposed addition to ECMAScript to ensure certain properties of an import (e.g. “this module is JSON, and is not intended to be executable JavaScript code”). They were reinvented as a proposal called import attributes. As part of the transition, they swapped from using the assert keyword to using the with keyword.[^1]\n\n[^1]: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html#restrictions-on-import-assertions-under---module-nodenext\n\n\n\n```typescript\n// An import assertion ❌ - not future-compatible with most runtimes.\nimport data from \"./data.json\" assert { type: \"json\" };\n// An import attribute ✅ - the preferred way to import a JSON file.\nimport data from \"./data.json\" with { type: \"json\" };\n```\n\n\n\u003ca name=\"dont-use-preservemodules\"\u003e\u003c/a\u003e\n### dont use `preserveModules` \n\nCJS build contains `preserveModules` enabled and that creates bundle problems\n- all external modules are copied to the `dist` folder and shipped to `npm`, so all users download them twice\n\n- Useing a browser field and `preserveModules` don't copy files specified by this field, so it creates issues like https://github.com/TanStack/query/issues/3965\n\n\u003ca name=\"moduleresolution-nodenext-only-allows-defined-import-paths\"\u003e\u003c/a\u003e\n### `moduleResolution` `NodeNext` only allows defined import paths \n\nWhen setting moduleResolution in our tsconfig to NodeNext. When this is enabled, the module resolution will only allow importing from paths that are defined within the exports config. Because only `types/index.d.ts` is available for import, it can cause these kinds of embedded imports to fail:\n\n```javascript\nimport(\"@stitches/react/types/css-util\").CSS\n```\n\nAn alternative would be to ensure that all types are exported from the types/index.d.ts file.\n\n\u003e see https://github.com/stitchesjs/stitches/pull/1115#issue-1441336030\n\n\u003ca name=\"correct-manifest\"\u003e\u003c/a\u003e\n#### correct manifest\n\n```diff\n  \"exports\": {\n    \".\": {\n      \"require\": \"./dist/index.cjs\",\n      \"import\": \"./dist/index.mjs\",\n      \"types\": \"./types/index.d.ts\"\n    },\n+    \"./types/*\": {\n+      \"types\": \"./types/*.d.ts\"\n    },\n    \"./global\": \"./dist/index.global.js\"\n  },\n  \"files\": [\n    \"dist/*.cjs\",\n    \"dist/*.js\",\n    \"dist/*.map\",\n    \"dist/*.mjs\",\n    \"types/*.d.ts\"\n  ],\n```  \n\n\u003ca name=\"load-esmtsmts\"\u003e\u003c/a\u003e\n## `load-esm.{ts,mts}`\n\n```typescript\nimport { URL } from 'url';\n\n/**\n * This uses a dynamic import to load a module which may be ESM.\n * CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript\n * will currently, unconditionally downlevel dynamic import into a require call.\n * require calls cannot load ESM code and will result in a runtime error. To workaround\n * this, a Function constructor is used to prevent TypeScript from changing the dynamic import.\n * Once TypeScript provides support for keeping the dynamic import this workaround can\n * be dropped.\n *\n * @param modulePath The path of the module to load.\n * @returns A Promise that resolves to the dynamically imported module.\n */\nexport function loadEsmModule\u003cT\u003e(modulePath: string | URL): Promise\u003cT\u003e {\n  return new Function('modulePath', `return import(modulePath);`)(modulePath) as Promise\u003cT\u003e;\n}\n```\n\n\u003ca name=\"motivation\"\u003e\u003c/a\u003e\n## Motivation\n\nEstablishing the best way to support cjs and esm and how to structure project to enable that (see results.txt for more info)\n\n\u003ca name=\"opt-in-compiler-options\"\u003e\u003c/a\u003e\n### Opt in compiler options\n\n**disable** the following compiler options:\n\n\u003e `tsconfig.json`\n```jsonc\n\"esModuleInterop\": false,\n\"allowSyntheticDefaultImports\": false\n```\n\nThe two flags `esModuleInterop` and `allowSyntheticDefaultImports` enable interoperation between ES Modules and CommonJS, AMD, and UMD modules for emit from TypeScript and type resolution by TypeScript respectively. \n\nUnfortunately these options are viral: **enabling them in a package requires all downstream consumers to enable them as well** .  The TLDR is due to the way CommonJS and ES Modules interoperate with bundlers (Webpack, Parcel, etc.). \n\n\u003ca name=\"solution\"\u003e\u003c/a\u003e\n### Solution\n\n\u003e**Warning**   \n\u003e setting both `allowSyntheticDefaultImports` and `esModuleInterop` to `false` may break your build.\n\nConsumers can now opt into these semantics, it also does not require them to do so. \nConsumers **can always safely use alternative import syntaxes (including falling back to require() and import()),** or can enable these flags and opt into this behavior themselves.\n\n\u003ca name=\"other-compiler-options-affecting-the-build-result\"\u003e\u003c/a\u003e\n#### Other Compiler Options Affecting the Build Result\n\n- `extends`   \n- `importsNotUsedAsValues`   \n- `preserveValueImports`   \n- `jsxFactory`   \n- `jsxFragmentFactory`   \n\n\u003ca name=\"suggested-tsconfig-values\"\u003e\u003c/a\u003e\n#### Suggested `tsconfig` values\n\n```jsonc\n\"useDefineForClassFields\": true,\n```\n```jsonc\n\"isolatedModules\": true,\n```\n\n\u003e [source, vitejs developer guide: vitejs.dev/guide/features.html#typescript-compiler-options](https://vitejs.dev/guide/features.html#typescript-compiler-options)\n\n\u003ca name=\"side-by-side-compare\"\u003e\u003c/a\u003e\n## Side by Side Compare\n\n\u003ca name=\"nodeassert\"\u003e\u003c/a\u003e\n### node:assert\n\n\u003e**Note**    \n\u003e[See the NodeJs Assertion Documentation for more information](https://nodejs.org/api/assert.html#assert)\n    \n\u003ca name=\"modern\"\u003e\u003c/a\u003e\n#### Modern\n\n```typescript\nimport { strict as assert } from 'node:assert'; // ESM\nconst assert = require('node:assert').strict;   // CJS\n```\n    \n```typescript\nimport assert from 'node:assert/strict';       // ESM\nconst assert = require('node:assert/strict');  // CJS\n```\n    \n```typescript\nimport { strict as assert } from 'node:assert'; // ESM\nconst assert = require('node:assert/strict');   // CJS\n```\n    \n\u003ca name=\"legacy\"\u003e\u003c/a\u003e\n#### Legacy\n   \n```typescript\nimport assert from 'node:assert';      // ESM\nconst assert = require('node:assert'); // CJS\n```\n\n\u003ca name=\"tldr\"\u003e\u003c/a\u003e\n## TLDR\n\n```javascript\n(?\u003c=(?:(?:import|require)\\(|(?:import(?:\\s|.)*from))\\s*(?:\\\"|\\'))(.*)(?=\\\"|\\')\n```\n```javascript\n// test file for regex above\nimport(\"./module\")\nimport('./module')\nrequire(\"./module\")\nrequire('./module')\nimport * as Namespace from \"./module\"\nimport Namespace from \"./module\"\nimport { variableOne } from \"./module\"\nimport { variableOne, variableTwo } from \"./module\"\nimport { \n  variableOne,\n  variableTwo,\n} from \"./module\"\nimport { variable as somethingElse } from \"./module\"\n```\n\n```javascript\n// code generated \nconst regex = /(?\u003c=(?:(?:import|require)\\(|(?:import(?:\\s|.)*from))\\s*(?:\\\"|\\'))(.*)(?=\\\"|\\')/gm;\n\n// Alternative syntax using RegExp constructor\n// const regex = new RegExp('(?\u003c=(?:(?:import|require)\\\\(|(?:import(?:\\\\s|.)*from))\\\\s*(?:\\\\\"|\\\\\\'))(.*)(?=\\\\\"|\\\\\\')', 'gm')\n\nconst str = `import(\"./module\")\nimport('./module')\nrequire(\"./module\")\nrequire('./module')\nimport * as Namespace from \"./module\"\nimport Namespace from \"./module\"\nimport { variableOne } from \"./module\"\nimport { variableOne, variableTwo } from \"./module\"\nimport { \n  variableOne,\n  variableTwo,\n} from \"./module\"\nimport { variable as somethingElse } from \"./module\"\n`;\nlet m;\n\nwhile ((m = regex.exec(str)) !== null) {\n    // This is necessary to avoid infinite loops with zero-width matches\n    if (m.index === regex.lastIndex) {\n        regex.lastIndex++;\n    }\n    \n    // The result can be accessed through the `m`-variable.\n    m.forEach((match, groupIndex) =\u003e {\n        console.log(`Found match, group ${groupIndex}: ${match}`);\n    });\n}\n```\n\n\u003ca name=\"cheatsheet\"\u003e\u003c/a\u003e\n### Cheatsheet\n\n```ts twoslash\n// import the entire object\nimport json from './example.json'\n```\n\n```ts twoslash\n// import a root field as named exports - helps with tree-shaking!\nimport { field } from './example.json'\n```\n\nUse the Type-Only Imports and Export syntax to avoid potential problems like type-only imports being incorrectly bundled. for example:\n\n```ts twoslash\nimport type { T } from 'only/types'\nexport type { T }\n```\n\u003e [source, typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export)\n\n\u003ca name=\"avoid-default-exports-and-prefer-named-exports\"\u003e\u003c/a\u003e\n## Avoid Default Exports and Prefer Named Exports\n\n\u003ca name=\"context\"\u003e\u003c/a\u003e\n### Context\n\nWhen CommonJS was the primary authoring format, the best practice was to export only one thing from a module using the module.exports = ... format. This aligned with the UNIX philosophy of \"Do one thing well\". The module would be consumed (const localName = require('the-module');) without having to know the internal structure.\n\nNow, ESModules are the primary authoring format. They have numerous benefits, such as compile-time verification of exports, and standards-defined semantics. They have a similar mechanism known as \"default exports\", which allows for a consumer to import localName from 'the-module';. This is implicitly the same as `import { default as localName } from 'the-module';`.\n\nHowever, there are numerous reasons to avoid default exports, as documented by others before:\n\n\u003e NOTE. https://humanwhocodes.com/blog/2019/01/stop-using-default-exports-javascript-module/\n\n\u003ca name=\"summary\"\u003e\u003c/a\u003e\n### Summary\n\nThey add indirection by encouraging a developer to create local names for modules, increasing cognitive load and slowing down code comprehension: import TheListThing from 'not-a-list-thing';.\n- They thwart tools, such as IDEs, that can automatically rename and refactor code.\n- They promote typos and mistakes, as the imported member is completely up to the consuming developer to define.\n- They are ugly in CommonJS interop, as the default property must be manually specified by the consumer. This is often hidden by Babel's module interop.\n- They break re-exports due to name conflicts, forcing the developer to manually name each.\n- Using named exports helps prevent needing to rename symbols, which has myriad benefits. A few are:\n\n  IDE tools like \"Find All References\" and \"Go To Definition\" function\n  Manual codebase searching (\"grep\", etc) is easier with a unique symbol\n\n\u003ca name=\"decision\"\u003e\u003c/a\u003e\n## Decision\n\n\u003e source: https://backstage.io/docs/architecture-decisions/adrs-adr004\n\nWe will make each exported symbol traceable through index files all the way down to the root of the package, src/index.ts. Each index file will only re-export from its own immediate directory children, and only index files will have re-exports. This gives a file tree similar to this:\n\n```\nindex.ts\ncomponents/index.ts\n          /ComponentX/index.ts\n                     /ComponentX.tsx\n                     /SubComponentY.tsx\nlib/index.ts\n   /UtilityX/index.ts\n            /UtilityX.ts\n            /helper.ts\n```          \n\nTo check whether for example SubComponentY is exported from the package, it should be possible to traverse the index files towards the root, starting at the adjacent one. If there is any index file that doesn't export the previous one, the symbol is not publicly exported. For example, if components/ComponentX/index.ts exports SubComponentY, but components/index.ts does not re-export ./ComponentX, one should be certain that SubComponentY is not exported outside the package. This rule would be broken if for example the root index.ts re-exports ./components/ComponentX\n\nIn addition, index files that are re-exporting other index files should always use wildcard form, that is:\n\n```typescript\n// in components/index.ts\nexport * from './ComponentX';\n```\n\nIndex files that are re-exporting symbols from non-index files should always enumerate all exports, that is:\n\n```typescript\n// in components/ComponentX/index.ts\nexport { ComponentX } from './ComponentX';\nexport type { ComponentXProps } from './ComponentX';\n```\n\nInternal cross-directory imports are allowed from non-index modules to index modules, for example:\n\n```typescript\n// in components/ComponentX/ComponentX.tsx\nimport { UtilityX } from '../../lib/UtilityX';\n```\nImports that bypass an index file are discouraged, but may sometimes be necessary, for example:\n\n```typescript\n// in components/ComponentX/ComponentX.tsx\nimport { helperFunc } from '../../lib/UtilityX/helper';\n```\n\n\u003ca name=\"ecmascript-module-support-in-nodejs\"\u003e\u003c/a\u003e\n### ECMAScript Module Support in Node.js\n\n\u003e source https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/\n\nFor the last few years, Node.js has been working to support running ECMAScript modules (ESM). This has been a very difficult feature to support, since the foundation of the Node.js ecosystem is built on a different module system called CommonJS (CJS). Interoperating between the two brings large challenges, with many new features to juggle; however, support for ESM in Node.js is now largely implemented in Node.js 12 and later, and the dust has begun to settle.\n\nThat’s why TypeScript 4.5 brings two new module settings: node12 and nodenext.\n```json\n{\n    \"compilerOptions\": {\n        \"module\": \"nodenext\",\n    }\n}\n```\n\nThese new modes bring a few high-level features which we’ll explore here.\n\ntype in package.json and New Extensions\nNode.js supports a new setting in package.json called type. \"type\" can be set to either \"module\" or \"commonjs\".\n```json\n{\n    \"name\": \"my-package\",\n    \"type\": \"module\",\n\n    \"//\": \"...\",\n    \"dependencies\": {\n    }\n}\n```\n\u003ca name=\"mjs-cjs--mts-cts--dmts-and-dcts\"\u003e\u003c/a\u003e\n### `.mjs`, `.cjs`, == `.mts`, `.cts` \u0026\u0026 `.d.mts` and `.d.cts`.\n\nNode.js supports two extensions to help with this: `.mjs` and `.cjs`. `.mjs` files are always ES modules, and `.cjs` files are always CommonJS modules, and there’s no way to override these.\n\nIn turn, TypeScript supports two new source file extensions: `.mts` and `.cts`. When TypeScript emits these to JavaScript files, it will emit them to `.mjs` and `.cjs` respectively.\n\nFurthermore, TypeScript also supports two new declaration file extensions:` .d.mt`s and `.d.cts`. When TypeScript generates declaration files for `.mts` and `.cts`, their corresponding extensions will be `.d.mts` and `.d.cts`.\n\nUsing these extensions is entirely optional, but will often be useful even if you choose not to use them as part of your primary workflow.\n\n\n\u003ca name=\"avoid-export-default\"\u003e\u003c/a\u003e\n## Avoid Export Default\n\n\u003e source:  TypeScript Deep Dive\n\n\u003e [source https://basarat.gitbook.io/typescript/main-1/defaultisbad](https://basarat.gitbook.io/typescript/main-1/defaultisbad)\n\n\u003e Consider you have a file foo.ts with the following contents:\n\n\nConsider you have a file `foo.ts` with the following contents:\n\nYou would import it (in `bar.ts`) using ES6 syntax as follows:\n\nThere are a few maintainability concerns here:\n\n-   If you refactor `Foo` in `foo.ts` it will not rename it in `bar.ts`.\n    \n\n-   If you end up needing to export more stuff from `foo.ts` (which is what many of your files will have) then you have to juggle the import syntax.\n    \n\nFor this reason I recommend simple exports + destructured import. E.g. `foo.ts`:\n\n```typescript\nimport { Foo } from \"./foo\";\n```\nBelow I also present a few more reasons.\n\n\u003ca name=\"poor-discoverability\"\u003e\u003c/a\u003e\n### Poor Discoverability\n\nDiscoverability is very poor for default exports. You cannot explore a module with intellisense to see if it has a default export or not.\n\nWith export default you get nothing here (maybe it does export default / maybe it doesn't `¯\\_(ツ)_/¯`):\n\n```typescript\nimport /\\* here \\*/ from 'something';\n```\nWithout export default you get a nice intellisense here:\n\n```typescript\nimport { /\\* here \\*/ } from 'something';\n```\n\n\u003ca name=\"autocomplete\"\u003e\u003c/a\u003e\n### Autocomplete\n\nIrrespective of if you know about the exports, you even autocomplete at this `import {/*here*/} from \"./foo\";` cursor location. Gives your developers a bit of wrist relief.\n\n\u003ca name=\"commonjs-interop\"\u003e\u003c/a\u003e\n### CommonJS interop\n\nWith `default` there is horrible experience for commonJS users who have to `const {default} = require('module/foo');` instead of `const {Foo} = require('module/foo')`. You will most likely want to rename the `default` export to something else when you import it.\n\n\u003ca name=\"typo-protection\"\u003e\u003c/a\u003e\n### Typo Protection\n\nYou don't get typos like one dev doing `import Foo from \"./foo\";` and another doing `import foo from \"./foo\";`\n\n\u003ca name=\"typescript-auto-import\"\u003e\u003c/a\u003e\n### TypeScript auto-import\n\nAuto import quickfix works better. You use `Foo` and auto import will write down `import { Foo } from \"./foo\";` cause its a well-defined name exported from a module. Some tools out there will try to magic read and _infer_ a name for a default export but magic is flaky.\n\n\u003ca name=\"re-exporting\"\u003e\u003c/a\u003e\n### Re-exporting\n\nRe-exporting is common for the root `index` file in npm packages, and forces you to name the default export manually e.g. `export { default as Foo } from \"./foo\";` (with default) vs. `export * from \"./foo\"` (with named exports).\n\n\u003ca name=\"dynamic-imports\"\u003e\u003c/a\u003e\n### Dynamic Imports\n\nDefault exports expose themselves badly named as `default` in dynamic `import`s e.g.\n\n```typescript\nconst HighCharts \\= await import('https://code.highcharts.com/js/es-modules/masters/highcharts.src.js');\n\nHighCharts.default.chart('container', { ... }); // Notice \\`.default\\`\n```\nMuch nicer with named exports:\n```typescript\nconst {HighCharts} \\= await import('https://code.highcharts.com/js/es-modules/masters/highcharts.src.js');\n\nHighCharts.chart('container', { ... }); // Notice \\`.default\\`\n```\n\n\u003ca name=\"es-module-interop\"\u003e\u003c/a\u003e\n### ES Module Interop\n\n\n\u003e [esModuleInterop, https://www.typescriptlang.org/tsconfig#esModuleInterop](https://www.typescriptlang.org/tsconfig#esModuleInterop)\n\nBy default (with `esModuleInterop` false or not set) TypeScript treats CommonJS/AMD/UMD modules similar to ES6 modules. In doing this, there are two parts in particular which turned out to be flawed assumptions:\n\na namespace import like `import * as moment from \"moment\"` acts the same as `const moment = require(\"moment\")`\n\na default import like `import moment from \"moment\"` acts the same as `const moment = require(\"moment\").default`\n\nThis mis-match causes these two issues:\n\n- the ES6 modules spec states that a namespace import (import * as x) can only be an object, by having TypeScript treating it the same as = require(\"x\") then TypeScript allowed for the import to be treated as a function and be callable. That’s not valid according to the spec.\n\n- while accurate to the ES6 modules spec, most libraries with CommonJS/AMD/UMD modules didn’t conform as strictly as TypeScript’s implementation.\n\n\n\u003ca name=\"note\"\u003e\u003c/a\u003e\n##### Note\n\nThe namespace import `import * as fs from \"fs\"` only accounts for properties which are **owned** (basically properties set on the object and not via the prototype chain) on the imported object. If the module you’re importing defines its API using inherited properties, you need to use the default import form (`import fs from \"fs\"`), or *disable esModuleInterop*.\n\n\n\n\u003ca name=\"needs-two-lines-for-non-class--non-function\"\u003e\u003c/a\u003e\n### Needs two lines for non-class / non-function\n\nCan be one statement for function / class e.g.\n\n```typescript\nexport default function foo() {\n}\n```\n\nCan be one statement for _non named / type annotated_ objects e.g.:\n\n\n```typescript\nexport default {\n  notAFunction: 'Yeah, I am not a function or a class',\n  soWhat: 'The export is now *removed* from the declaration'\n};\n```\n\nBut needs two statements otherwise:\n\n```typescript\n// If you need to name it (here \\`foo\\`) for local use OR need to annotate type (here \\`Foo\\`)\n\nnotAFunction: 'Yeah, I am not a function or a class',\n\nsoWhat: 'The export is now \\*removed\\* from the declaration'\n};\nexport default foo;\n```\n\n\u003ca name=\"reactjs---named-exports\"\u003e\u003c/a\u003e\n### React.js - Named Exports\n\n\u003e [source, https://reactjs.org/docs/code-splitting.html#named-exports](https://reactjs.org/docs/code-splitting.html#named-exports)\n\n\nReact.lazy currently only supports default exports. If the module you want to import uses named exports, you can create an intermediate module that reexports it as the default. This ensures that tree shaking keeps working and that you don’t pull in unused components.\n\n```javascript\n// ManyComponents.js\nexport const MyComponent = /* ... */;\nexport const MyUnusedComponent = /* ... */;\n```\n\n```javascript\n// MyComponent.js\nexport { MyComponent as default } from \"./ManyComponents.js\";\n```\n\n```javascript\n// MyApp.js\nimport React, { lazy } from 'react';\nconst MyComponent = lazy(() =\u003e import(\"./MyComponent.js\"));\n```\n\n\u003ca name=\"-type\"\u003e\u003c/a\u003e\n## {} type\n\n\u003e [Below is copied from this comment, see https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492](https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492)\n\nWe will not be removing `{}` from the rule defaults, as it is an unsafe type because it doesn't work how people think it works, and in most cases it allows weakly typed code.\n\n\nThis is the exact reason that the rule bans the `{}` ***type***.\nIt's a common misconception that the `{}` ***type*** is the same as the `{}` ***value***.\nBut as the rule's message states: _this is not the case_!\n\nThe ***type*** `{}` doesn't mean \"any empty object\", it means \"any non-nullish value\".\n\nThis is obviously a huge type safety hole!\n\nFor example - the following code is _completely type-check valid_, even though it might make no sense to be:\n\n```typescript\ninterface AAA {\n  aaa: {};\n}\n\nconst x: AAA = { aaa: true };\n```\n[repl](https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgILuQbwFDOXAgLiwF8BubE7bBAexAGcxkAPY9VZAXi3yOTBQArinLYgA)\n\n[It's also important to note that empty interfaces behave in exactly the same way as the `{}` type!](https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgILuQbwFDOXAgLmQCEyBubAX21ElkRTJKxuwQHsQBnMZAD2LpUyALxZ8RZGCgBXFFUpA), which is why we have the [`no-empty-interface`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-interface.md) lint rule.\n\n----\n\nUnfortunately, there's no _type_ in TS that means \"an empty object\".\n\nThere are the following options for you:\n\n\u003ca name=\"if-you-want-a-type-that-means-empty-object\"\u003e\u003c/a\u003e\n### If you want a type that means \"empty object\"\n\nYou can use a type similar to this type.\n\n```typescript\ntype EmptyObject = Record\u003cstring, never\u003e; // or {[k: string]: never}\n\nconst a: EmptyObject = { a: 1 };  // expect error\nconst b: EmptyObject = 1;         // expect error\nconst c: EmptyObject = () =\u003e {};  // expect error\nconst d: EmptyObject = null;      // expect error\nconst e: EmptyObject = undefined; // expect error\nconst f: EmptyObject = {};        // NO ERROR - as expected\n```\n[ts playground repl](https://www.typescriptlang.org/play?#code/C4TwDgpgBAogtmUB5ARgKwgY2FAvFAJSwHsAnAEwB4BnYUgSwDsBzAGikYgDcJSA+ANwAoIZmKNaUAIYAuWAmTosOfAG9pcgIxQAvgKhQA9IagQAHpGynSpMqPGSUc+IhCoMV-Jv0Hfv46YWyta2pPYSOJjOCm5KnlAAFACUeHxQqnoGAeaWOLyh4ZLk0a7uwfiMAK4ANtU+ftlBVvl2YhGmJYoeKlCVjOQQAGZMEOT6jbkhrQ44g52x3XjpmX7+JgBySLAEBEgEUAC00tSBuaNCQA)\n\n\u003ca name=\"if-you-are-using-react-and-you-want-to-define-type-props--\"\u003e\u003c/a\u003e\n### If you are using React, and you want to define `type Props = {}`.\n\nThis is ***technically*** safe in this instance, [because under the hood the `{}` type is passed into an intersection type](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/6fd37a55773b23e00a19418d9b5aad912087c982/types/react/index.d.ts#L501) (see the note at the end of this comment for why this is safe).\n\nHowever, there is no way for us to statically analyze and know that this is a safe usage.\nTo work around this, consider reconfiguring the lint rule to match your repository's coding style.\nYou can use the following config to allow it:\n\n```json\n{\n  \"rules\": {\n    \"@typescript-eslint/ban-types\": [\n      \"error\",\n      {\n        \"extendDefaults\": true,\n        \"types\": {\n          \"{}\": false\n        }\n      }\n    ]\n  }\n}\n```\n\nConsider using [an eslint overrides config](https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns) to limit the scope of this change to just react component files, to help ensure you're keeping your codebase as safe as possible.\n\nAs an aside - it's worth noting that `{}` is a very weird anomaly in TypeScript, because there is just one case where it actually does mean something akin to \"empty object\"; in an intersection type.\n\n```typescript\ntype T1 = { a: 1 } \u0026 {};\nconst t11: T1 = { a: 1 };\nconst t12: T1 = true; // expected error\n\ntype T2 = true \u0026 {};\nconst t21: T2 = true;\nconst t22: T2 = false; // expected error\nconst t23: T2 = {}; // expected error\n\n```\n[repl](https://www.typescriptlang.org/play?#code/C4TwDgpgBAKgjFAvFA3lAhgLiggvlAMlVwG4AoAYwHsA7AZ2CmDjm3iVQ2z3OvseYAmNgmTAATgFcIJKAHo5UCAA9IFYBAAmS8eKriyZUJFiCOE6YWK9aDJoNanzUmZVsDBwp8gBm6ADZ0MvKKKmoa2hC6+m789gDMbGbIKKQhSqoQ6lo6egZAA)\n\nIn this usage, the type essentially is a no-op, and means nothing at all.\n\nIn all other usages, [including in the `extends` clause of a generic type parameter](https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABMOcA8AVRBTAHlbMAEwGdEBvAXwD4AKABwEMAnRgWwC5EMBKCygFACUcWlGYhsPANzDUtAIwy5oqspG0wIADbaZiAPQGcuetmjYiOZszjMBQA), it means \"anything non-nullish\".\n\n_Originally posted by @bradzacher in https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492_\n\n\n\u003ca name=\"genericobject\"\u003e\u003c/a\u003e\n### `GenericObject`\n\n```typescript\n/**\n * Helper to avoid writing `Record\u003cstring, unknown\u003e` everywhere you would usually use \"object\".\n *\n * @example (data: GenericObject) =\u003e void\n * @example variables: GenericObject\u003cstring\u003e\n *\n * @see https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-632833366\n */\nexport type GenericObject\u003cT = unknown\u003e = Record\u003cstring, T\u003e;\n```\n\n\u003ca name=\"module-related-host-hooks\"\u003e\u003c/a\u003e\n###  Module-related host hooks\n\n\u003e [source, https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-module-system](https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-module-system)\n\n\u003e NOTE. Although the JavaScript specification speaks in terms of \"scripts\" versus \"modules\", in general this specification speaks in terms of classic scripts versus module scripts, since both of them use the script element.\n\nThe JavaScript specification defines a syntax for modules, as well as some host-agnostic parts of their processing model. This specification defines the rest of their processing model: how the module system is bootstrapped, via the `[script](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element)` element with `[type](https://html.spec.whatwg.org/multipage/scripting.html#attr-script-type)` attribute set to \"`module`\", and how modules are fetched, resolved, and executed. [\\[JAVASCRIPT\\]](https://html.spec.whatwg.org/multipage/references.html#refsJAVASCRIPT)\n\nAlthough the JavaScript specification speaks in terms of \"scripts\" versus \"modules\", in general this specification speaks in terms of [classic scripts](https://html.spec.whatwg.org/multipage/webappapis.html#classic-script) versus [module scripts](https://html.spec.whatwg.org/multipage/webappapis.html#module-script), since both of them use the `[script](https://html.spec.whatwg.org/multipage/scripting.html#the-script-element)` element.\n\n`modulePromise = [import(specifier)](https://tc39.es/ecma262/#sec-import-calls)`\n\nReturns a promise for the module namespace object for the [module script](https://html.spec.whatwg.org/multipage/webappapis.html#module-script) identified by specifier. This allows dynamic importing of module scripts at runtime, instead of statically using the `import` statement form. The specifier will be [resolved](https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier) relative to the [active script](https://html.spec.whatwg.org/multipage/webappapis.html#active-script)'s [base URL](https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url).\n\nThe returned promise will be rejected if an invalid specifier is given, or if a failure is encountered while [fetching](https://html.spec.whatwg.org/multipage/webappapis.html#fetch-an-import()-module-script-graph) or [evaluating](https://html.spec.whatwg.org/multipage/webappapis.html#run-a-module-script) the resulting module graph.\n\nThis syntax can be used inside both [classic](https://html.spec.whatwg.org/multipage/webappapis.html#classic-script) and [module scripts](https://html.spec.whatwg.org/multipage/webappapis.html#module-script). It thus provides a bridge into the module-script world, from the classic-script world.\n\n`url = [import.meta](https://tc39.es/ecma262/#sec-meta-properties) .url`\n\nReturns the [active module script](https://html.spec.whatwg.org/multipage/webappapis.html#active-script)'s [base URL](https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url).\n\nThis syntax can only be used inside [module scripts](https://html.spec.whatwg.org/multipage/webappapis.html#module-script).\n\nA module map is a [map](https://infra.spec.whatwg.org/#ordered-map) keyed by [tuples](https://infra.spec.whatwg.org/#tuple) consisting of a [URL record](https://url.spec.whatwg.org/#concept-url) and a [string](https://infra.spec.whatwg.org/#string). The [URL record](https://url.spec.whatwg.org/#concept-url) is the [request URL](https://fetch.spec.whatwg.org/#concept-request-url) at which the module was fetched, and the [string](https://infra.spec.whatwg.org/#string) indicates the type of the module (e.g. \"`javascript`\"). The [module map](https://html.spec.whatwg.org/multipage/webappapis.html#module-map)'s values are either a [module script](https://html.spec.whatwg.org/multipage/webappapis.html#module-script), null (used to represent failed fetches), or a placeholder value \"`fetching`\". [Module maps](https://html.spec.whatwg.org/multipage/webappapis.html#module-map) are used to ensure that imported module scripts are only fetched, parsed, and evaluated once per `[Document](https://html.spec.whatwg.org/multipage/dom.html#document)` or [worker](https://html.spec.whatwg.org/multipage/workers.html#workers).\n\nSince [module maps](https://html.spec.whatwg.org/multipage/webappapis.html#module-map) are keyed by (URL, module type), the following code will create three separate entries in the [module map](https://html.spec.whatwg.org/multipage/webappapis.html#module-map), since it results in three different (URL, module type) [tuples](https://infra.spec.whatwg.org/#tuple) (all with \"`javascript`\" type):\n\n```typescript\nimport \"https://example.com/module.mjs\";\nimport \"https://example.com/module.mjs#map-buster\";\nimport \"https://example.com/module.mjs?debug=true\";\n```\n\nThat is, URL [queries](https://url.spec.whatwg.org/#concept-url-query) and [fragments](https://url.spec.whatwg.org/#concept-url-fragment) can be varied to create distinct entries in the [module map](https://html.spec.whatwg.org/multipage/webappapis.html#module-map); they are not ignored. Thus, three separate fetches and three separate module evaluations will be performed.\n\nIn contrast, the following code would only create a single entry in the [module map](https://html.spec.whatwg.org/multipage/webappapis.html#module-map), since after applying the [URL parser](https://url.spec.whatwg.org/#concept-url-parser) to these inputs, the resulting [URL records](https://url.spec.whatwg.org/#concept-url) are equal:\n\n```typescript\nimport \"https://example.com/module2.mjs\";\nimport \"https:example.com/module2.mjs\";\nimport \"https://///example.com\\\\module2.mjs\";\nimport \"https://example.com/foo/../module2.mjs\";\n```\n\nSo in this second example, only one fetch and one module evaluation will occur.\n\nNote that this behavior is the same as how [shared workers](https://html.spec.whatwg.org/multipage/workers.html#sharedworker) are keyed by their parsed [constructor url](https://html.spec.whatwg.org/multipage/workers.html#concept-sharedworkerglobalscope-constructor-url).\n\nSince module type is also part of the [module map](https://html.spec.whatwg.org/multipage/webappapis.html#module-map) key, the following code will create two separate entries in the [module map](https://html.spec.whatwg.org/multipage/webappapis.html#module-map) (the type is \"`javascript`\" for the first, and \"`css`\" for the second):\n\n```html\n\u003cscript type=module\u003e\n  import \"https://example.com/module\";\n\u003c/script\u003e\n\u003cscript type=module\u003e\n  import \"https://example.com/module\" assert { type: \"css\" };\n\u003c/script\u003e\n```\n\nThis can result in two separate fetches and two separate module evaluations being performed. This is a [willful violation](https://html.spec.whatwg.org/multipage/introduction.html#willful-violation) of a constraint recommended (but not required) by the import assertions specification stating that each call to [HostResolveImportedModule](https://html.spec.whatwg.org/multipage/webappapis.html#hostresolveimportedmodule(referencingscriptormodule,-modulerequest)) with the same (referencingScriptOrModule, moduleRequest.\\[\\[Specifier\\]\\]) pair must return the same [Module Record](https://tc39.es/ecma262/#sec-source-text-module-records). [\\[JSIMPORTASSERTIONS\\]](https://html.spec.whatwg.org/multipage/references.html#refsJSIMPORTASSERTIONS)\n\nIn practice, due to the as-yet-unspecified memory cache (see issue [#6110](https://github.com/whatwg/html/issues/6110)) the resource may only be fetched once in WebKit and Blink-based browsers. Additionally, as long as all module types are mutually exclusive, the module type check in [fetch a single module script](https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script) will fail for at least one of the imports, so at most one module evaluation will occur.\n\nThe purpose of including the type in the [module map](https://html.spec.whatwg.org/multipage/webappapis.html#module-map) key is so that an import with the wrong type assertion does not prevent a different import of the same specifier but with the correct type from succeeding.\n\nJavaScript module scripts are the default import type when importing from another JavaScript module; that is, when an `import` statement lacks a `type` import assertion the imported module script's type will be JavaScript. Attempting to import a JavaScript resource using an `import` statement with a `type` import assertion will fail:\n\n```html\n\u003cscript type=\"module\"\u003e\n    // All of the following will fail, assuming that the imported .mjs files are served with a\n    // JavaScript MIME type. JavaScript module scripts are the default and cannot be imported with\n    // any import type assertion.\n    import foo from \"./foo.mjs\" assert { type: \"javascript\" };\n    import foo2 from \"./foo2.mjs\" assert { type: \"js\" };\n    import foo3 from \"./foo3.mjs\" assert { type: \"\" };\n    await import(\"./foo4.mjs\", { assert: { type: null } });\n    await import(\"./foo5.mjs\", { assert: { type: undefined } });\n\u003c/script\u003e\n```\n\nTo resolve a module specifier given a [URL](https://url.spec.whatwg.org/#concept-url) base URL and a [string](https://infra.spec.whatwg.org/#string) specifier, perform the following steps. It will return either a [URL record](https://url.spec.whatwg.org/#concept-url) or failure.\n\n1.  Apply the [URL parser](https://url.spec.whatwg.org/#concept-url-parser) to specifier. If the result is not failure, return the result.\n    \n2.  If specifier does not start with the character U+002F SOLIDUS (`/`), the two-character sequence U+002E FULL STOP, U+002F SOLIDUS (`./`), or the three-character sequence U+002E FULL STOP, U+002E FULL STOP, U+002F SOLIDUS (`../`), return failure.\n    \n    This restriction is in place so that in the future we can allow custom module loaders to give special meaning to \"bare\" import specifiers, like `import \"jquery\"` or `import \"web/crypto\"`. For now any such imports will fail, instead of being treated as relative URLs.\n    \n3.  Return the result of applying the [URL parser](https://url.spec.whatwg.org/#concept-url-parser) to specifier with base URL.\n    \n\nThe following are valid module specifiers according to the above algorithm:\n\n-   `https://example.com/apples.mjs`\n-   `http:example.com\\pears.js` (becomes `http://example.com/pears.js` as step 1 parses with no base URL)\n-   `//example.com/bananas`\n-   `./strawberries.mjs.cgi`\n-   `../lychees`\n-   `/limes.jsx`\n-   `data:text/javascript,export default 'grapes';`\n-   `blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f`\n\nThe following are valid module specifiers according to the above algorithm, but will invariably cause failures when they are [fetched](https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script):\n\n-   `javascript:export default 'artichokes';`\n-   `data:text/plain,export default 'kale';`\n-   `about:legumes`\n-   `wss://example.com/celery`\n\nThe following are not valid module specifiers according to the above algorithm:\n\n-   `https://eggplant:b/c`\n-   `pumpkins.js`\n-   `.tomato`\n-   `..zucchini.mjs`\n-   `.\\yam.es`\n\n\n\u003ca name=\"customizing-module-resolution\"\u003e\u003c/a\u003e\n## Customizing module resolution\n\n\u003e [source, https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#customizing-module-resolution]\n\nYou can override the standard way the compiler resolves modules by implementing optional method: C`ompilerHost.resolveModuleNames`:\n\n```typescript\nCompilerHost.resolveModuleNames(moduleNames: string[], containingFile: string): string[].\n```\n\nThe method is given a list of module names in a file, and is expected to return an array of size `moduleNames`.length, each element of the array stores either:\n\nan instance of `ResolvedModule` with non-empty property `resolvedFileName` - resolution for corresponding name from moduleNames array or undefined if module name cannot be resolved.\n\nYou can invoke the standard module resolution process via calling `resolveModuleName`:\n\n```typescript\nresolveModuleName(moduleName: string, containingFile: string, options: CompilerOptions, moduleResolutionHost: ModuleResolutionHost): ResolvedModuleNameWithFallbackLocations.\n```\n\nThis function returns an object that stores result of module resolution (value of `resolvedModule` property) as well as list of file names that were considered candidates before making current decision.\n\n```typescript\nimport * as ts from \"typescript\";\nimport * as path from \"path\";\n\nfunction createCompilerHost(options: ts.CompilerOptions, moduleSearchLocations: string[]): ts.CompilerHost {\n  return {\n    getSourceFile,\n    getDefaultLibFileName: () =\u003e \"lib.d.ts\",\n    writeFile: (fileName, content) =\u003e ts.sys.writeFile(fileName, content),\n    getCurrentDirectory: () =\u003e ts.sys.getCurrentDirectory(),\n    getDirectories: path =\u003e ts.sys.getDirectories(path),\n    getCanonicalFileName: fileName =\u003e\n      ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),\n    getNewLine: () =\u003e ts.sys.newLine,\n    useCaseSensitiveFileNames: () =\u003e ts.sys.useCaseSensitiveFileNames,\n    fileExists,\n    readFile,\n    resolveModuleNames\n  };\n\n  function fileExists(fileName: string): boolean {\n    return ts.sys.fileExists(fileName);\n  }\n\n  function readFile(fileName: string): string | undefined {\n    return ts.sys.readFile(fileName);\n  }\n\n  function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) =\u003e void) {\n    const sourceText = ts.sys.readFile(fileName);\n    return sourceText !== undefined\n      ? ts.createSourceFile(fileName, sourceText, languageVersion)\n      : undefined;\n  }\n\n  function resolveModuleNames(\n    moduleNames: string[],\n    containingFile: string\n  ): ts.ResolvedModule[] {\n    const resolvedModules: ts.ResolvedModule[] = [];\n    for (const moduleName of moduleNames) {\n      // try to use standard resolution\n      let result = ts.resolveModuleName(moduleName, containingFile, options, {\n        fileExists,\n        readFile\n      });\n      if (result.resolvedModule) {\n        resolvedModules.push(result.resolvedModule);\n      } else {\n        // check fallback locations, for simplicity assume that module at location\n        // should be represented by '.d.ts' file\n        for (const location of moduleSearchLocations) {\n          const modulePath = path.join(location, moduleName + \".d.ts\");\n          if (fileExists(modulePath)) {\n            resolvedModules.push({ resolvedFileName: modulePath });\n          }\n        }\n      }\n    }\n    return resolvedModules;\n  }\n}\n\nfunction compile(sourceFiles: string[], moduleSearchLocations: string[]): void {\n  const options: ts.CompilerOptions = {\n    module: ts.ModuleKind.AMD,\n    target: ts.ScriptTarget.ES5\n  };\n  const host = createCompilerHost(options, moduleSearchLocations);\n  const program = ts.createProgram(sourceFiles, options, host);\n\n  /// do something with program...\n}\n```\n\n\u003ca name=\"parseroptionsmoduleresolver\"\u003e\u003c/a\u003e\n### parserOptions.moduleResolver\n\n\u003e [source, https://www.npmjs.com/package/@typescript-eslint/parser](https://www.npmjs.com/package/@typescript-eslint/parser)\n\nDefault: `undefined`\n\nThis option allows you to provide a custom module resolution. The value should point to a JS file that default exports (`export default`, or `module.exports =`, or `export =`) a file with the following interface:\n\n```typescript\ninterface ModuleResolver {\n  version: 1;\n  resolveModuleNames(\n    moduleNames: string[],\n    containingFile: string,\n    reusedNames: string[] | undefined,\n    redirectedReference: ts.ResolvedProjectReference | undefined,\n    options: ts.CompilerOptions,\n  ): (ts.ResolvedModule | undefined)[];\n}\n```\nRefer to the TypeScript Wiki for an example on how to write the `resolveModuleNames` function.\n\nNote that if you pass custom programs via `options.program`s this option will not have any effect over them (you can simply add the custom resolution on them directly).\n\n\u003ca name=\"fixing-es6-import-syntax-with-verbatimmodulesyntax\"\u003e\u003c/a\u003e\n## Fixing ES6 Import Syntax with `verbatimModuleSyntax` \n\nIn your code, you're using ES6 import syntax (\n\n```typescript\nimport { hash } from \"@stablelib/sha256\")\n```\nThis is not compatible with CommonJS modules when `verbatimModuleSyntax  is enabled.\n\nTo fix this issue, you have a few options:\n\n\u003ca name=\"use-require-instead-of-import\"\u003e\u003c/a\u003e\n### Use require() instead of import\n\nReplace the import statement with a require statement, like this:\n\n```typescript\nconst { hash } = require(\"@stablelib/sha256\");\n```\nThis will use the CommonJS module system, which is compatible with the verbatimModuleSyntax setting.\n\n\u003ca name=\"disable-verbatimmodulesyntax\"\u003e\u003c/a\u003e\n### Disable verbatimModuleSyntax\n\nIf you're using a configuration file (e.g., tsconfig.json) or a build tool (e.g., Webpack), you can disable verbatimModuleSyntax to allow ES6 import syntax. For example, in tsconfig.json, you can add the following setting:\n\n```jsonc\n{\n  \"compilerOptions\": {\n    // ... other options ...\n    \"verbatimModuleSyntax\": false\n  }\n}\n```\nThis will allow you to use ES6 import syntax without issues.\n\n\u003ca name=\"use-a-compatibility-layer\"\u003e\u003c/a\u003e\n### Use a compatibility layer\n\nIf you're using a library that only provides ES6 modules, you can use a compatibility layer like esm to convert the ES6 module to a CommonJS module. For example:\n\n```typescript\nconst esm = require(\"esm\");\nconst { hash } = esm(\"@stablelib/sha256\");\n```\nThis will allow you to use the ES6 module with your CommonJS code.\n\nChoose the option that best fits your project's requirements, and let me know if you have any further questions!\n\n\u003ca name=\"license\"\u003e\u003c/a\u003e\n## License\n\nCC-SA-2.5\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsambacha%2Ftypescript-cjs-esm-tests","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsambacha%2Ftypescript-cjs-esm-tests","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsambacha%2Ftypescript-cjs-esm-tests/lists"}