Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import package.json into Typescript file without including it in the compiled output?

Using Typescript 2.9 I am able to successfully import the local package.json file and use the values. However I now have the issue where the package.json file is included in the compiled output, when I just want the resulting JS files to use the actual package.json.

My package has the following files:

src/
  index.ts
package.json
tsconfig.json

My index.ts imports the package.json:

import pkg = require("../package.json");

My tsconfig.json looks like this:

{
  "compilerOptions": {
    "outDir": "./lib",
    "module": "commonjs",
    "resolveJsonModule": true,
    "esModuleInterop": true
  },
  "include": [
    "src/**/*"
  ]
}

Ideally the result would be:

lib/
  index.js
package.json

However what I actually get is:

lib/
  src/
    index.js
  package.json
package.json
like image 399
Tyler Johnson Avatar asked Jun 27 '18 19:06

Tyler Johnson


People also ask

How do I get package json files in TypeScript?

Typescript should be able to do it as follows: import * as pack from "../package. json" // access name and version like this: console. log(pack.name);

How do I include a file in TypeScript?

In the TypeScript file which is to be imported must include an export form and the main file where the class is imported must contain an import form, by which TypeScript can identify the file which is used.

What is include in Tsconfig?

tsconfig include The include property specifies the files to be included in the TypeScript project. You can either include files or file paths like ./src/** to specify what should be included.


2 Answers

🚩 This approach won't work for ESM targets. If you trying to create an ES6 Module, you'll have to use a different solution.

I am using TypeScript 3.5.1 and if I import the package.json with the require() function then it is not copied over to the compile output so the output looks like your ideal result.

My tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "lib": ["es2015", "dom"],
    "sourceMap": true,
    "strict": true,
    "moduleResolution": "node",
    "downlevelIteration": true
    "outDir": "./ts-out",
    "noImplicitAny": false,
    "suppressImplicitAnyIndexErrors": false
  },
  "include": [
    "./src"
  ]
}

And I just import it like this:

const pkg = require('../package.json');

I have found this solution in Facebook's Jest framework source code (they are using Lerna + TypeScript): https://github.com/facebook/jest/blob/master/packages/jest-core/src/version.ts

like image 131
Dominik Avatar answered Oct 17 '22 07:10

Dominik


You want a few somewhat contradictory things:

  1. You want to import package.json, meaning you are treating it as source
  2. But you don't want it to be compiled/emitted to the outDir as is done for source
  3. You don't want the output path within outDir to include "src/", which is what happens when you make rootDir point to the project root rather than the src root, which is the only way you can get the import statement to work.

solution: use separate Typescript sub-projects

These contradictions won't be contradictions if you logically break your project into separate sub-projects. You will need Typescript 3's new Project References feature.

We'll treat the src directory and the root directory containing package.json as separate projects. Each will have its own tsconfig file:

  1. Give the src dir its own project.

    ./src/tsconfig.json:

     {
       "compilerOptions": {
         "rootDir": ".",
         "outDir": "../lib/",
         "resolveJsonModule": true
       },
       "references": [      // this is how we declare a dependency from
         { "path": "../" }  // this project to the one at the root dir`
       ]
     }
    
  2. Give the root dir its own project.

    ./tsconfig.json:

     {
       "compilerOptions": {
         "rootDir": ".",
         "outDir": ".",  // if out path for a file is same as its src path, nothing will be emitted
         "resolveJsonModule": true,
         "composite": true  // required on the dependency project for references to work
       },
       "files": [         // by whitelisting the files to include, TS won't automatically
         "package.json"   // include all source below root, which is the default.
       ]
     }
    

    Because for the root sub-project's output is the self-same directory, and because the source path and output path for package.json end up the same, tsc won't do anything.... effectively a no-op.

  3. run tsc --build src and voilà! The result will be:

     lib/
       index.js
     package.json
    
like image 29
Inigo Avatar answered Oct 17 '22 07:10

Inigo