How to exclude `node_modules/@types/**/node_modules`?
Asked Answered
S

3

11

I have run into a situation where a type definition in node_modules/@types is installing its own @types dependencies, and these "nested" @types conflict with my top level @types.

@types
|-angular //v1.5
|-angular-ui-bootstrap
  |-node_modules
    |-@types
       |-angular //v1.6

How can I exclude node_modules/@types/**/node_modules in my tsconfig?

One caveat - I am using awesome-typescript-loader, which may have some limitations.

What I've tried:

1 - file glob in the exclude property to exclude the nested node_modules

    compilerOptions.exclude: '../node_modules/@types/**/node_modules'

2 - declaring types explicitly

    compilerOptions.types: ['angular', 'angular-ui-bootstrap']

3 - file glob in the typeRoots to exclude nested node_modules

    compilerOptions.typeRoots: ['../node_modules/@types/**/!(node_modules)']

What I've learned

1 - exclude doesn't seem to work with @types

2 - including a type with "types" means including its dependent @types

3 - typeRoots doesn't seem to work with file globs (or I'm writing the glob wrong)

Related:

Exclude @types typings in installed dependencies

https://github.com/Microsoft/TypeScript/issues/9731

https://github.com/Microsoft/TypeScript/issues/11917

https://github.com/s-panferov/awesome-typescript-loader/issues/492

tsconfig - How to ignore @types/whatever/node_modules for a specific directory?

Details on my environment

"node": "8.6.0", "typescript: "2.8.3", "awesome-typescript-loader": "5.0.0", "webpack": "4.8.3",

Squirrel answered 25/5, 2018 at 13:42 Comment(4)
Have you tried just updating your version to 1.6? – Absher
@TimBJames πŸ™‚ Haven't tried upgrading, although I wish I could! This is for a sprawling AngularJS application that still uses ngController in some parts. I'm hoping for a solution that I can implement now, without coordinating with teammates and doing extensive regression testing. – Squirrel
I hacked a solution in the package.json, but I would still like to know how conflicting dependencies can be obviated. ` "postinstall": "node rimraf.js node_modules/@types/angular-ui-bootstrap/node_modules"` – Squirrel
I think the issue isn't going to be easy to resolve due to the different dependency versions. Looks like angular-ui-bootstrap is always going to want the later version of the types. – Absher
L
5

A solution I found for this was to specify the node_modules/@types directory in the tsconfig.json paths setting.

Here's the snippet I changed in my tsconfig.json, which you should be able to adapt for your use case. I needed to modify my baseUrl and my paths settings.

   ...
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "*": ["./node_modules/@types/*"]
    }
   ...

In my case I'm using absolute urls in my TS project, so my local files are all relative to @/. I think if you are not using an absolute url like that, you should have something like the following for your config:

   ...
    "baseUrl": ".",
    "paths": {
      "*": ["./src/*", "./node_modules/@types/*"]
    }
   ...

Here's my complete tsconfig.json, which probably has a lot of irrelevant information, for reference.

{
  "compilerOptions": {
    "outDir": "./build/",
    "sourceMap": true,
    "allowJs": true,
    "checkJs": true,
    "jsx": "react",
    "target": "es2017",
    "module": "commonjs",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "removeComments": false,
    "preserveConstEnums": true,
    "skipLibCheck": true,
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "*": ["./node_modules/@types/*"]
    }
  },
  "include": ["**/*", "*"],
  "exclude": ["build", "node_modules", "coverage"]
}

Lynx answered 8/2, 2019 at 22:30 Comment(0)
S
1

Use peerDependencies to ensure you only have one version of a dependency.

i.e. If I am using typings for angular and angular-mocks, angular-mocks will have its own @types/angular

@types/angular  // => 1.5.8
@types/angular-mocks // => 1.5.8
@types/angular-mocks/node_modules/@types/angular // => *

To prevent two version of @types/angular from being installed, declare @types/angular as a peerDependency in your package.json file.

Squirrel answered 1/8, 2018 at 13:35 Comment(0)
F
0

Use the following postinstall script in your package.json:

for d in node_modules/@types/*/ ; do
  rm -rf ${d}node_modules
done

This will loop through the @types and remove unwanted transitive type dependencies.

Franconia answered 26/5, 2021 at 5:34 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.