TypeScript: typeRoots is not finding custom declaration file
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.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 41
- Comments: 24 (2 by maintainers)
Commits related to this issue
- fix: 解决第三方ts声明引入无效问题 - <https://github.com/microsoft/TypeScript/issues/22217> — committed to Hokori23/Pro_design by deleted user 3 years ago
- Support `.d.ts`s and make them visible in tests If a project lacks types for one or more dependencies, it is customary to fill in those types via ambient modules in the form of `.d.ts` files. Unfortu... — committed to MetaMask/metamask-module-template by mcmire 2 years ago
- Support `.d.ts`s and make them visible in tests If a project lacks types for one or more dependencies, it is customary to fill in those types via [ambient modules][1] in the form of `.d.ts` (type def... — committed to MetaMask/metamask-module-template by mcmire 2 years ago
@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:
This would be vastly preferable to having to scan GitHub Issues, StackExchange, etc. for information.
"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 yourdeclare 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:
One thing I don’t understand here is that:
tsconfig.base.json:
And a directory structure:
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 intonode_modules/@types
it’ll magically work and get picked up, which suggests thetypeRoots
does absolutely nothing asnode_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
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.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.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 thoughtpaths
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.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.
I still think it would be helpful to have the docs updated as stated in my previous comment @typescript-bot
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
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 addedtypes
to my type roots and still no luck 😦@gaurav5430’s comment got me on the right track!
My original folder layout:
My
tsconfig.json
:I was still getting errors and I could not understand why. Turns out,
@types/index.d.ts
should actually be named after the module that doesn’t have types. So, for me I had to change:@types/index.d.ts
to@types/csv-to-js-parser.d.ts
.(Contents of that file being
declare module "csv-to-js-parser";
)FINALLY
Also, this issue is super annoying.
In my case, the issue was that I’ve been using
include
andexclude
. The issue is that I was trying to access the global types from a file that wasn’t included.so I just remove the
include
and kept only theexclude
, and now works as expectedOh 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.
for anyone finding this issue i was able to resolve this in my code base by adding custom
types
to thetsconfig.base.json
after declaring them in thetypeRoots
tsconfig.base.json
type dir
SO post - second answer
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.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 IDEI 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
but the below code works:
This also works:
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 ?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.@ALFmachine big ups for the
types
aftertypeRoots
… can’t believe the order matters 😮