Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typeRoots is not finding custom declaration file #22217

Closed
lwilli opened this issue Feb 28, 2018 · 17 comments
Closed

typeRoots is not finding custom declaration file #22217

lwilli opened this issue Feb 28, 2018 · 17 comments
Labels

Comments

@lwilli
Copy link

@lwilli lwilli commented Feb 28, 2018

TypeScript Version:
Version 2.6.2

Search Terms:
declaration file for module exporting function, external module, npm package, third-party module

Code
src/testFile.ts:

import getFieldList = require('graphql-list-fields');

src/@types/graphql-list-fields/index.d.ts:

// Doing just this below (as suggested by the Typescript Handbook does not work 
// and results in the tsc error under **Actual behavior** below
import { GraphQLResolveInfo } from 'graphql';
declare function getFieldList(info: GraphQLResolveInfo): string[];
export = getFieldList;

// The code below is what actually works instead of the above
/*
declare module 'graphql-list-fields' {
    import { GraphQLResolveInfo } from 'graphql';
    function getFieldList(info: GraphQLResolveInfo): string[];
    export = getFieldList;
}
*/

Expected behavior:
Compiling without errors.

Actual behavior:
Error when running tsc:

src/testFile.ts(1,31): error TS7016: Could not find a declaration file for module 'graphql-list-fields'. '/node_modules/graphql-list-fields/index.js' implicitly has an 'any' type.
Try `npm install @types/graphql-list-fields` if it exists or add a new declaration (.d.ts) file containing `declare module 'graphql-list-fields';`

graphql-list-fields is an NPM package that I'm trying to use, which currently has no published type declarations.

After reading through the Typescript Handbook's section on declaration files, I found that I am trying to write a declaration file for a modular library and should use the module-function.d.ts declaration file template. This is how I came up with the code in index.d.ts above, but the compiler still complains about not having the declaration file for the module 'graphql-list-fields'. After trial and error, we found that adding declare module 'graphql-list-fields' around everything worked without compiler errors.

We tried setting "typeRoots": ["./node_modules/@types", "./src/@types"] in tsconfig.json, as mentioned in the tsconfig docs but that still did not work without declare module 'graphql-list-fields'. This seems to be an issue because tsc is not finding the type declaration in the directories specified in typeRoots.

Related Issues:
3019, 8335

@lwilli lwilli changed the title Add documentation for how to write a declaration file for a module exporting a function TypeRoots is not finding custom declaration file Feb 28, 2018
@lwilli lwilli changed the title TypeRoots is not finding custom declaration file typeRoots is not finding custom declaration file Feb 28, 2018
@mhegazy
Copy link
Contributor

@mhegazy mhegazy commented Mar 2, 2018

"typeRoots" is meant for global code. i.e. something that is declarated in the global namespace, and you want to include it. this is why your declare module 'graphql-list-fields' {.. works, since it just declares a module with that name in the global namespace.

For modules, they have thier own scope, all you need is path mappig..

somethign like:

{
    "compilerOptions": {
        "target": "es5",
        "baseUrl": "./",
        "paths": {
            "*" : ["src/@t`ypes/*"]
        }
    }
}`
@lwilli
Copy link
Author

@lwilli lwilli commented Mar 2, 2018

Thanks for clearing that up @mhegazy. I think it would be helpful if this was explained more in the TypeScript docs, possibly under the declaration files section.

@mhegazy
Copy link
Contributor

@mhegazy mhegazy commented Mar 2, 2018

TypeRoots is really a support we have added for back compat with typings and to allow migration, so we tried to keep it out of the docs as much as possible to avoid confusion.

Not sure if this fits in the declaration file section. we do have a note about it in https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping

I can add a note in the declaration file section about module resolution section as a whole.

give that section a read and let us know if you still find docs in it lacking

@lwilli
Copy link
Author

@lwilli lwilli commented Mar 2, 2018

Oh I see. Yeah, that is the page that I needed to begin with. I think it would be nice to have at least a brief mention of path mapping and maybe a link to that doc somewhere under https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html.

@typescript-bot
Copy link
Collaborator

@typescript-bot typescript-bot commented Mar 22, 2018

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@lwilli
Copy link
Author

@lwilli lwilli commented Mar 22, 2018

I still think it would be helpful to have the docs updated as stated in my previous comment @typescript-bot

@ericdrobinson
Copy link

@ericdrobinson ericdrobinson commented Jul 24, 2018

TypeRoots is really a support we have added for back compat with typings and to allow migration, so we tried to keep it out of the docs as much as possible to avoid confusion.

@mhegazy Having a supported feature with little-to-no documentation is what drives confusion. Please properly document features like this but be liberal with your warning language. For example:

Note: This feature is provided for backwards compatibility with typings to support migration. See the release notes [here] for more information.

This would be vastly preferable to having to scan GitHub Issues, StackExchange, etc. for information.

@kaiwa
Copy link

@kaiwa kaiwa commented Sep 1, 2019

Thx a fucking ton @mhegazy ! 🎉 That path entry for @types was finally the missing piece which made my non-standard project setup work. I spent days on this.

@YEriin
Copy link

@YEriin YEriin commented Sep 16, 2019

If you don't mind slow down your application starting process little, you can just add TS_NODE_FILES=true to your package.json's start script and all custom declaration file will be found.

@KrzysztofMadejski
Copy link

@KrzysztofMadejski KrzysztofMadejski commented Oct 18, 2019

I'm now getting:

The following changes are being made to your tsconfig.json file:
  - compilerOptions.paths must not be set (aliased imports are not supported)

and this option is being deleted.

@kaiwa
Copy link

@kaiwa kaiwa commented Dec 1, 2019

@KrzysztofMadejski that's done by CRA, not TS itself.

@Roaders
Copy link

@Roaders Roaders commented May 8, 2020

This thread says that typeroots is really for backwards compatibility. I am trying to use it to author types for definitively typed. How else would I properly test these types without typeroots? I have generated types using dts-gen and added types to my type roots and still no luck :-(

@abhijithvijayan
Copy link

@abhijithvijayan abhijithvijayan commented Sep 10, 2020

@Roaders did you find the solution to use dts-gen generated types?

Edit: Solved with #22217 (comment)

@intellix
Copy link

@intellix intellix commented Sep 13, 2020

One thing I don't understand here is that:

tsconfig.base.json:

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

And a directory structure:

/node_modules/@types/something/index.d.ts
/types/something-else/index.d.ts

It won't get picked up at all in my nrwl/nx repository. I can try a million things but if I move that something-else folder into node_modules/@types it'll magically work and get picked up, which suggests the typeRoots does absolutely nothing as node_modules/@types is magically handled.

Marking typeRoots as deprecated and saying it works in a weird/quirky way would have at least stopped me trying to use it.

The only way I've managed to add local types each time I've needed to, is by spending hours fighting with my tsconfig.base.json and stumbling upon the mhegazy comment above

@andyperlitch
Copy link

@andyperlitch andyperlitch commented Sep 29, 2020

I kept getting bitten by this and forgetting about having to configure the paths option as well, so I created a simple repository with the proper settings. Hope it helps someone.

@pikeas
Copy link

@pikeas pikeas commented Dec 29, 2020

I'm being bit by this as well. I couldn't get custom types for a 3rd party project picked up no matter what I tried. It was working for a while by copying the folder into node_modules/@types, but tsc or another process validates that directory and deletes unexpected files.

{
    "paths": {
          "something": ["types/something"]
    },
    // typeRoots does not need to be set
}

This seems to work but it was extremely unintuitive and under-documented. It didn't occur to me to try paths until I found this thread after many hours of failures. I thought paths was for "A series of entries which re-map imports to lookup locations relative to the baseUrl" (https://www.typescriptlang.org/tsconfig#paths), and unrelated to resolving type declarations.

@gaurav5430
Copy link

@gaurav5430 gaurav5430 commented Mar 14, 2021

I have a library written in javascript, which exposes type declarations to external consumers. These type declarations are generated automatically using the typescript compiler in a types folder. In the consumer, it works fine, but I would like to use the same declarations within the library as well for intellisense/autocomplete within the IDE

I initially thought that typeRoots would be the way to go, but as discussed above, it seems to be only applicable for global modules / types.

as @mhegazy suggested, I tried using paths to accomplish this.
I can't make it work with relative paths, though it works fine with aliased absolute paths.

The below does not work

// src/packageA
...some code
// src/@types/packageA
...generated type definitions
// usage within the library - does not work
import packageA from '../../packageA'
// tsconfig
paths: {
  "*" : ["@types/*", "*"]
}

but the below code works:

// src/packageA
...some code
// src/@types/packageA
...generated type definitions
// usage within the library - works, but this is not what I want
import packageA from 'packageA'
// tsconfig
paths: {
  "packageA" : ["@types/packageA/*", "*"] //notice the aliasing here
}

This also works:

// src/packageA
...some code
// src/@types/packageA
...generated type definitions
// usage within the library - works, but this is not what I want
import packageA from 'absolute/path/from/base/url/'
// tsconfig
paths: {
  "*" : ["@types/*", "*"]
}

Note that both of the working versions require some change in my webpack module resolution as well to work correctly, but at least typescript seems to be resolving them correctly.

Am i missing something here, or is it generally not possible to make paths work with relative paths ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet