TypeScript: Error when importing untyped JS modules
TypeScript Version: 2.2.1
Steps
- In a simple TS project in VSCode, add
"adal-node": "^0.1.22",topackage.jsonand runnpm install. This is a JS library with no types. - Import the library in your
index.tsas below
Code
import adal from "adal-node";
Expected behavior: Per this bug’s resolution #3019 this code should compile with no errors
Actual behavior: tsc.exe: ‘Could not find a declaration file for module ‘adal-node’. ‘e:/proj/node_modules/adal-node/lib/adal.js’ implicitly has an ‘any’ type.’
References: see #3019 and all its linked bugs
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 27
- Comments: 46 (12 by maintainers)
Commits related to this issue
- chore(ts): Allow importing untyped JS modules By allowing implied any type declarations, which prevents the following error: "Could not find a declaration file for module 'foo'. '/node_modules/foo/Fo... — committed to roalcantara/typescript-cli-boilerplate by roalcantara 6 years ago
- chore(ts): Allow importing untyped JS modules By allowing implied any type declarations, which prevents the following error: "Could not find a declaration file for module 'foo'. '/node_modules/foo/Fo... — committed to roalcantara/typescript-cli-boilerplate by roalcantara 6 years ago
- Update Typescript to v4; Fix build See https://github.com/rollup/plugins/issues/287#issuecomment-626517864 See https://github.com/microsoft/TypeScript/issues/15031 — committed to quantargo/react-layout by deleted user 4 years ago
@Spongman Actually, you can just have a
global.d.tsat your project root with following content:It automatically makes all js modules any while ts modules keep working as intended.
Because you have turned on
noImplicitAny. You need to get around it by doingdeclare module 'adal-node'(ordeclare module "*", I have yet to try this myself)why does the noImplicitAny check fire when importing .js files? surely when you’re importing a .js file you’re explicitly declaring everything within it as
any?it seems too heavy a burden to require everything to have a @types or for the user to create a .d.ts file just for this check not to fire.
this IMHO really kills Anders’ claim of ‘drop-in replacement’ for javascript.
It is still impossible to import untyped Javascript modules.
I’ve spent the past few hours trying to figure out how to use
adapter.jswith Typescript, and I’ve run into no end of problems. At this point, I’m ready to give up again on Typescript.I’ve saved
adapter.jsin thesrc/directory, along withmain.ts. Things I’ve tried that haven’t worked:7:25 Cannot find module ‘adapter.js’.
7:25 Cannot find module ‘adapter’.
5:16 Invalid module name in augmentation, module ‘adapter.js’ cannot be found.
5:16 Invalid module name in augmentation, module ‘adapter’ cannot be found.
7:25 Could not find a declaration file for module ‘./adapter.js’. ‘PROJECT/src/adapter.js’ implicitly has an ‘any’ type.
ERROR in PROJECT/src/main.ts 5:16 Invalid module name in augmentation. Module ‘./adapter.js’ resolves to an untyped module at ERROR in PROJECT/src/main.ts 6:25 Could not find a declaration file for module ‘./adapter.js’. ‘PROJECT/src/adapter.js’ implicitly has an ‘any’ type.
5:16 File ‘PROJECT/src/adapter.d.ts’ is not a module. 6:25 File ‘PROJECT/src/adapter.d.ts’ is not a module.
5:1 Import assignment cannot be used when targeting ECMAScript modules. Consider using ‘import * as ns from “mod”’, ‘import {a} from “mod”’, ‘import d from “mod”’, or another module format instead.
Is there any way to do something simple like
import * as BabiliPlugin from "babili-webpack-plugin";withnoImplicitAnyenabled without getting warning TS7016 (“could not find a declaration file…implicitly has an ‘any’ type”)?Typescript should act smarter in these cases. WHY ON EARTH we need to define a type definition if we explicitly import a JS module.
Hello! Could you please clarify where do I put this declaration file:
And how do I instruct compiler to actually use it?
This should be behind another config flag or another frictionless solution, using
noImplicitAnyis best practice for TS, but creating ad.tsfile and filling it with empty module declarations is just annoying.This is still a JS world and we’re just trying to exist in it. I never had a manually created
d.tsfile (only auto-generated) and now it seems like a new requirement.I’ve been hunting around for this answer for the better part of a month now. I found a solution that works in VS Code that isn’t a wholesale disabling of all validation for javascript/typescript and also did not require that I add files/declarations to a repository that is not mine.
Add one or both of these lines to your user settings:
Unlike
"javascript.validate.enable": false(which you should not use), the above setting will remove those annoying[ts] Could not find a declaration file for moduleerrors for untyped module imports and it will still play nice with linters and give you appropriate and relevant errors.oops! you’re right that I have
noImplicitAnycompiler option set in mytsconfig.json. Totally forgot about it as its one of my default configs to writing TS.I think I can work with the solution you posted on the other thread. Thanks for the quick feedback ! Appreciate it.
@mhegazy : I’m still not sure how to correctly use this
declare moduleandimportsyntax to import untyped JS modules. Could you please provide a small snippet demonstrating how to accomplish that? Thanks.Add a declaration for your module, e.g.:
or simply:
@SCLeoX OMG THANK YOU. Hours of pounding my head against outdated docs and absolutely terrible error messages from tsc. If this simple workaround was the front page of http://www.typescriptlang.org then typescript adoption would double and it would also be the most useful thing on that website.
The issue as described by the OP seems fixed.
The other issue described in https://github.com/Microsoft/TypeScript/issues/15031#issuecomment-292011200, is because a module declaration (i.e
declare module 'adal-node' {... }) inside another module (i.e. a file with at least one top-levelimportorexport) is considered an “augmentation”. What you want is to move this declaration to a global .d.ts (as you want it to be in the global scope) file instead of keeping it in your module.I can confirm @SCLeoX’s suggestion. I just created a root-level
global.d.tsfile for untyped 3rd party libs. IMO,*is a bit too heavy-handed and I’d rather be explicit, so I simply took the module that the compiler was complaining about and declared it explicitly. But, that’s just my opinion.@slavafomin it worked for me in a similar case in another project, when I’ve put a new
index.d.tsin the project root directory (i.e. in the same directory as thetsconfig.jsonis located).i found this to be a helpful write up. https://medium.com/@chris_72272/migrating-to-typescript-write-a-declaration-file-for-a-third-party-npm-module-b1f75808ed2
in my case i just had to place the migration file in
src/@types/@okta/library-name/index.d.tsand as long as the part after @types matched the import, it was picked up. inside can be just 1 line declaring the moduleYou can put it anywhere as long as tsc can locate it. I.e. using
filesorincludein tsconfig.json.I put them under a
custom-typingsfolder.So it’s loading the module via the .js file also it seems. Do you have ‘allowJs’ set in your project config?
tried all the solutions not working! 😦
I took @SCLeoX’s suggestion and made the pattern-matching a bit narrower.
you do not need to include
@types. just add:Thanks I ended up forking and making a pull request with typings and adding an index.js outside the lib, which solves the issues
@aluanhaddad – yes ofcourse. sorry, that was a typo! updated my post
@balajikris Have you tried:
instead?