The "Invisible" Error Familiar to Every TypeScript Developer
You're writing TypeScript code, everything is going smoothly, but suddenly — a red squiggly line under the import. The compiler reports something alarming: Could not find a declaration file for module 'module-name'. '/path/to/module-name.js' implicitly has an 'any' type. If you've ever worked with TypeScript, you've likely encountered this message. It appears when you try to import a JavaScript module for which no declaration file (usually with a .d.ts extension) exists.
On Stack Overflow, this question has garnered thousands of views. And this is no coincidence: the problem seems complex, although in reality it has several simple and elegant solutions. In this article, we'll break down why the error occurs and compare four main approaches to fixing it. You'll learn which method to choose depending on the situation, and you'll be able to forget about "invisible" types forever.
Why Does TypeScript Require Declarations?
TypeScript is a superset of JavaScript that adds static typing. When you write import * as _ from 'lodash', TypeScript needs to know what types the variable _ has. If there is no .d.ts file for the module, the compiler cannot check types and assigns the module the type any by default. This breaks type strictness, so TypeScript warns you. In reality, this is not a runtime error but a compilation warning, though in strict projects (strict: true) it can block the build.
Now let's move on to the solutions. We'll look at four approaches, from the simplest to the most flexible.
Solution 1: Quick and Dirty — declare module
The simplest way is to create a declaration file manually. To do this, add a global.d.ts (or types.d.ts) file to your project and write:
// global.d.tsdeclare module 'module-name';This line tells TypeScript: "The module exists, but its type is any". The problem is solved, but you lose all the benefits of typing. This approach is good for quick prototypes or when the module is used in one or two places. However, for production projects, this is not the best choice.
- Pros: Minimal code, no need to install packages.
- Cons: The
anytype defeats the purpose of TypeScript; if the module updates, you won't know about API changes.
Solution 2: Using @types Packages
For most popular npm modules, there are separate packages with declarations. For example, for lodash it's @types/lodash. Install them via npm or yarn:
npm install --save-dev @types/lodashAfter this, TypeScript will automatically find the declarations, and the error will disappear. If you're using TypeScript 2.0+, it automatically looks for the @types folder. This is the standard and recommended method.
- Pros: Full typing, community support, automatic updates.
- Cons: Not all modules have
@types(e.g., for lesser-known libraries).
How to check if types exist? Go to the npm page or run npm info @types/module-name. If the package is not found, move on to the next solution.
Solution 3: Enabling allowJs and checkJs
If you're writing a project that mixes TypeScript and JavaScript, you can allow the compiler to check JS files. To do this, add the following to tsconfig.json:
{ "compilerOptions": { "allowJs": true, "checkJs": false }}The allowJs option allows importing JS modules into TS files. In this case, TypeScript will att