Search code examples
typescriptes6-modulescommonjstsconfig

Sharing file between commonjs and ejs, Typescript is not a module.ts(2306) on commonjs file


Background

I have a file that I need to share between the two repositories. The file contains one single object.

  • Repo A is set to only accept commonjs files (require("/path/to/file")) with no easy access for me to its babel configs.
  • Repo B is using ES6 import foo from "bar" import style, and I can play with its tsconfig.json.

I know that if I use modules.export = myObject it only works for the commonjs repo (repo A), and if I do export = myObject or export default myObject it only works for the ES6 repo (repo B).

Questions:

  1. Is this possible to make the same file work for both systems? I tried export = modules.export = myObject or any other combination but none works.

  2. How can I import the commonjs version in ES6 repo? I tried leaving it a commonjs modules.export = myObject file, but in Repo B when I do import foo from "path/to/file" it keeps crying the following message. it goes away the moment I change it to export = myObject, but then it wouldn't work for Repo A.

File '/path/to/file.ts' is not a module.ts(2306)

Notes

  1. I found that setting "esModuleInterop": true in my tsconfig.json should make it work, but no matter what I do, (any "module" value in tsconfig.json, turning on allowSyntheticDefaultImports) it doesn't work. I keep getting the same 2306 error.
  2. As I mentioned in the comment, it can be considered that the file contains a static object. (e.g. {a: 5, b: 8};)

tsconfig.json

The part in repo A that I am touching is the config file for Quasar and it's in vanilla JS.

Repo B is Typescript/Node project, and the relevant part of the tsconfig.json in there is:

"compilerOptions": {
        "baseUrl": ".",
        "esModuleInterop": true,
        "experimentalDecorators": true,
        "module": "commonjs",
        "moduleResolution": "node",
        "outDir": "dist",
        "strict": true,
        "sourceMap": true,
        "target": "es6",
        ...

Solution

  • I just found that as long as the file is a .json file with proper JSON format, one can use it both in ES6 (import) and CommonJS (require).

    Per this answer (and this article), for ES6 you need to enable "resolveJsonModule": true, in tsconfig.json and then you can have the content in both formats.

    So if the file content.json has the following content (with no comment or anything else):

    {
       "age": 34
    }
    

    then we will have ...

    import * as jsonContent from "../../content.json"
    
    console.log(jsonContent.age); // prints out 34
    

    as well as

    const jsonContent = require("../../content.json");
    
    console.log(jsonContent.age); // prints out 34
    

    They both print out the content successfully!