简体   繁体   中英

Global Type Declarations within a NX and NextJS monorepo

I've been looking around the web to try and find s nice solution to my problem but so far I have not.

I have a NX monorepo with NextJS and I am trying to create a global types/ folder that can be used by all of my apps and libs.

I had thought this would be quite simple, I would add a folder to the root and put all my .d.ts files in there. Then in the tsconfig.base.json I would add

"typeRoots": [
  "node_modules/@types",
  "node_modules/next/types",
  "types/"
]

I was hoping it would be as simple as that.

Allowing me to use my typing anywhere within the monorepo without having to import them.

Unfortunately, this didn't work. After lots of messing around I did manage to get it to work but only if the types/ folder was inside of the app, for example:

apps/
    /myApp/
          /types/            <- types here were detected
types/                       <- types here were not detected
tsconfig.base.json

This is no good for me as it would mean I would have to duplicate my types across all apps and libs.

The official recommendation from NX is to add a new lib just to store your types and then import it and use it in each of your apps and libs but this feels really clunky to me. Also, this doesn't really work with the idea of adding it to typeRoots within the tsbase.config.json

If anyone knows a better way this can be done I would love to hear about it.

Cheers.

Battling with the same issue right now. So far, this works for my project, but it's still not an ideal solution. I would much rather have a global provider.

apps/
    /myApp/
          tsconfig.app.json
types/                       <- add your .d.ts files here
tsconfig.base.json

in the tsconfig.app.json of each app add the following:

"include": ["../../types/**/*.d.ts"]

This will import all the type definitions stored in the global folder. But the configuration still has to be handled manually in each library and app.

Let me know if this is helpful or if you have found a better solution.

I cracked this problem in my repo this way: In the tsconfig.base.json add "./types to "typeRoots" .

"typeRoots": [..., "./types", ...]

Each type you want to reference should be in separate folder in index.d.ts file:

types/my-own-module/index.d.ts

Then you can add the typings to tsconfigs ( tsconfig.lib.json , `tsconfig.app.json in each project:

"types": [..., "my-own-module", ...]

The only downside is, that you need to add the typings to each project you need, it does not work globally, because usually each project has different "types" config.

An untested idea is to remove "types" from all configs and just add all needed types into the global tsconfig.

I've found a simple solution... In the root of your project create your types.d.ts file.

For each app and library, in the tsconfig.app.json or tsconfig.lib.json add this to the "files" section:

"../../types.d.ts"

截图示例

Works for me with nx version 12.10.1

Below setup works fine for all apps but not libs...


    // /index.d.ts
    declare global {
      namespace MyNamespace {
         interface MyInterface { ... }
      }
    }

Problem comes from the fact that extending tsconfig does not mean you're merging configurations. Extend in tsconfig is a complete override for the root level properties you declare in your extender configuration.

You can have a tsconfig.base.json in your project root like this:

...
"typeRoots": [
  "types",
  "node_modules/@types"
],
"types": [
  "node",
  "your-type"
]
...

Then you can place your own typing folder based on it:

<project-root>/types/your-type/index.d.ts

Check your tsconfig. (app|lib) .json files and look for overrides for property types and remove it completely.

This "solution" also has some drawbacks depending on the kind of project you are building. If it is a completely node project, i think it's okay to add node to the base tsconfig, but if the project is mixed or you need further app / lib specific type declarations this will fail and you'll end up copy-pasting the defined types from the base into app / lib tsconfig files.

I've created this nodejs script to do the dirty job:

/**
* Add an entry in the include property of a tsconfig file. 
* Requires node 14 or later
* Built to aid in global environment vars in nx projects.
* 
* put this script in a file called add-include.js in /usr/local/bin/ an 
* give it 755 permission.
*
* Put your common types in a folder, i.e: create a folder called types in 
* your project root, and put there some declarations files.

* then do a find with exec:
* 
* cd project-root
* find apps/ libs/ -name tsconfig.\*.json -exec add-include.js "../../types/*.d.ts" "{}" \;
*
* Recomendation: this is an undoable operation, so before executing 
* the code commit your work.
*/


const fs = require("fs");

if (process.argv.length < 4) {
  console.log(`Usage: add-include.js path-of-includes files`);
  console.log(`sample: add-include.js "../../*.d.ts" "{}"`);
  process.exit(-1);
}

const [,,newlib,...archivos] = process.argv;
archivos.forEach(a => {
  if (!fs.existsSync(a)) {
    console.log(`file ${a} not found, aborting`);
    process.exit(-1);
  }
})


archivos.forEach(a => {
  console.log(`processing ${a}`);
  const data = fs.readFileSync(a);
  const config = JSON.parse(data);

  if (!Array.isArray(config.include)) {
    console.log(`invalid file ${a}, no include property found, skipping`);
    return;
  }
  if (config.include.find(s => s === newlib)) {
    console.log(`${a} already has the value, skipping`);
    return;
  }
  config.include.push(newlib);
  fs.writeFileSync(a, JSON.stringify(config));
});

console.log(`Done, modified ${archivos.length} files`);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM