Skip to content

Fix: TypeScript Could Not Find Declaration File — Module Has No Type Information

FixDevs · (Updated: )

Part of:  React & Frontend Errors

Quick Answer

How to fix TypeScript 'could not find a declaration file for module' errors — installing @types packages, writing custom .d.ts files, module augmentation, and tsconfig paths.

The Error

TypeScript cannot find type information for a module:

Could not find a declaration file for module 'some-library'.
'/path/to/node_modules/some-library/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/some-library` if it exists
or add a new declaration (.d.ts) file containing `declare module 'some-library';`

Or an error after installing the types package:

TS2305: Module '@types/some-library' has no exported member 'SomeType'.

Or when importing from a subpath:

TS2307: Cannot find module 'some-library/utils' or its corresponding type declarations.

Or for a local file:

TS2307: Cannot find module './config' or its corresponding type declarations.

Why This Happens

TypeScript requires type information for every module you import. Unlike JavaScript, which resolves modules at runtime by finding the file, TypeScript resolves modules at compile time and also needs to know the shape (types, interfaces, function signatures) of what the module exports. When TypeScript cannot find type information, it does not know the types of anything you import from that module, so it either falls back to any (if noImplicitAny is off) or throws an error (if noImplicitAny is on, which is the default in strict mode).

The lookup process follows a specific order, and the error means every step failed:

  1. Bundled typestypes or typings field in the module’s package.json (included by the package itself)
  2. DefinitelyTyped@types/<package-name> in node_modules/@types/
  3. Type roots in tsconfig.json typeRoots field
  4. Declaration files.d.ts files matching the import path

The tricky part is that the error message suggests a simple fix (“install @types/x”), but several other configurations can prevent TypeScript from finding types even when they exist. A typeRoots override in tsconfig.json can exclude node_modules/@types. A types field in tsconfig.json can whitelist specific packages and exclude everything else. A .d.ts file that lacks an export statement becomes an ambient script instead of a module declaration, silently doing nothing.

Common specific causes:

  • No @types package exists — many smaller or newer packages do not have community-maintained types
  • Types package not installed — the @types package exists but was not installed
  • Package has exports map without types condition — modern packages using exports in package.json need a types condition for each export path; without it, TypeScript cannot find subpath types
  • moduleResolution setting mismatch — packages using exports fields require "moduleResolution": "bundler" or "node16", not the older "node" mode
  • Local file has wrong extension — importing ./config expects config.ts or config.d.ts to exist
  • typeRoots or types in tsconfig excludes the declaration — setting typeRoots replaces the default lookup; setting types whitelists specific packages

Diagnostic Timeline

Here is the process an experienced TypeScript developer follows when the “could not find declaration file” error appears.

Minute 0 — Read the error message carefully. The error tells you two things: the module name and the path TypeScript resolved it to. The path shows that TypeScript found the JavaScript file (/node_modules/some-library/index.js) but not a corresponding .d.ts file. This means the package exists and is installed — the issue is specifically about type declarations, not about a missing package.

Minute 1 — First instinct: “install @types/x.” Run npm install --save-dev @types/some-library. If it exists on npm, this usually fixes the error immediately. But many packages either bundle their own types (so no @types package is needed) or have no types at all (so no @types package exists). If npm install @types/some-library returns “404 Not Found”, the package does not have community types and you need a different approach.

Minute 2 — Check if the package bundles its own types. Open node_modules/some-library/package.json and look for a "types" or "typings" field. If it exists, the package ships its own type declarations and you should not need @types. If the field exists but TypeScript still cannot find the types, the problem is in your tsconfig.json — specifically moduleResolution, typeRoots, or types.

Minute 3 — Check typeRoots and types in tsconfig.json. This is the “ambient module trap” that catches experienced developers. If tsconfig.json sets "typeRoots": ["./src/types"], it replaces the default node_modules/@types lookup — your @types/ packages become invisible. If tsconfig.json sets "types": ["node", "jest"], only those two packages are loaded from @types — every other @types package is ignored. Either add "node_modules/@types" to typeRoots, or remove the types restriction, or add the specific package to the types list.

Minute 4 — Check moduleResolution. If the package uses the exports field in package.json (common in modern ESM packages), TypeScript’s default "moduleResolution": "node" (Node 10 algorithm) does not understand exports. Switch to "moduleResolution": "bundler" or "node16". This is the most common cause of “cannot find module” errors with packages that clearly have types — they publish types via exports conditions, not the legacy types field.

Minute 5 — Check for .d.ts files without exports. If you wrote a custom declaration file (src/types/some-library.d.ts) and it still does not work, check whether the file has an export statement. A .d.ts file with declare module 'x' { ... } but no top-level export or import is treated as an ambient script, which changes how TypeScript processes it. Adding export {}; at the bottom ensures it is treated as a module.

Minute 6 — Restart the TypeScript language server. After any change to tsconfig.json or .d.ts files, the TypeScript server in your IDE may cache stale information. In VS Code, run Ctrl+Shift+P then “TypeScript: Restart TS Server”. Then run npx tsc --noEmit from the terminal to verify the fix independently of the IDE.

Fix 1: Install the @types Package

Most popular JavaScript packages have community-maintained types on DefinitelyTyped:

npm install --save-dev @types/package-name

# Common examples
npm install --save-dev @types/node
npm install --save-dev @types/express
npm install --save-dev @types/lodash
npm install --save-dev @types/jest
npm install --save-dev @types/react @types/react-dom
npm install --save-dev @types/uuid
npm install --save-dev @types/multer

Find if an @types package exists:

npm search @types/package-name

# Or check the TypeScript registry
# https://www.typescriptlang.org/dt/search

After installing, verify TypeScript finds the types:

npx tsc --noEmit  # Should compile without the error now

Fix 2: Add a Module Declaration for Untyped Packages

If no @types package exists, declare the module’s type as any to silence the error:

// src/types/untyped-modules.d.ts
// Quick fix — module is typed as 'any'
declare module 'some-untyped-library';
declare module 'another-untyped-library';

Better approach — write minimal type declarations:

// src/types/some-library.d.ts
declare module 'some-library' {
  export interface Config {
    apiKey: string;
    timeout?: number;
  }

  export function initialize(config: Config): void;
  export function request(url: string): Promise<Response>;

  export default {
    initialize,
    request,
  };
}

Declare subpath modules:

// src/types/some-library.d.ts
declare module 'some-library' {
  export function mainFunction(): void;
}

declare module 'some-library/utils' {
  export function helperFunction(input: string): string;
}

declare module 'some-library/*' {
  // Wildcard — matches any subpath
  const value: unknown;
  export default value;
}

Pro Tip: Writing stub type declarations (with any types) is a faster path to progress than waiting for full type coverage. Once you have the stubs, you can refine individual types as you use them. Open a PR to DefinitelyTyped with your types to contribute back to the community.

Fix 3: Fix tsconfig.json to Include Declaration Files

TypeScript must be configured to find your custom .d.ts files:

// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",   // or "node16" for ESM
    "strict": true,
    "outDir": "./dist",
    "rootDir": "./src",

    // Where TypeScript looks for global type declarations
    "typeRoots": [
      "./node_modules/@types",
      "./src/types"            // Your custom .d.ts files directory
    ],

    // Explicit list of type packages to include (optional)
    // "types": ["node", "jest"]
  },
  "include": [
    "src/**/*",
    "src/types/**/*.d.ts"    // Ensure .d.ts files are included
  ]
}

Common Mistake: Setting typeRoots without including ./node_modules/@types. When you set typeRoots, it completely replaces the default behavior. If you only set "typeRoots": ["./src/types"], TypeScript stops looking in node_modules/@types entirely, which breaks @types/node, @types/react, and every other @types package.

Check that your types directory structure is correct:

src/
├── types/
│   ├── global.d.ts          # Global augmentations
│   ├── untyped-modules.d.ts # Declarations for untyped npm packages
│   └── env.d.ts             # Environment variable types
├── components/
└── index.ts

Fix 4: Fix moduleResolution for Modern Package Exports

Many modern packages use the exports field in package.json for subpath exports. The older "moduleResolution": "node" does not support this:

// The library's package.json (you can't change this)
{
  "exports": {
    ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
    "./utils": { "types": "./dist/utils.d.ts", "default": "./dist/utils.js" }
  }
}
// Your tsconfig.json — update moduleResolution
{
  "compilerOptions": {
    // OLD (Node 10 resolution — doesn't understand 'exports' field)
    // "moduleResolution": "node",

    // CORRECT — supports package exports
    "moduleResolution": "bundler",  // For Vite, esbuild, webpack bundlers
    // or:
    "moduleResolution": "node16",   // For Node.js 16+ native ESM
    // or:
    "moduleResolution": "nodenext" // For latest Node.js ESM support
  }
}

Verify the package includes type declarations for its exports:

cat node_modules/some-package/package.json | grep -A 20 '"exports"'
# Look for "types" entries in each export path

Fix 5: Module Augmentation for Third-Party Types

When a package’s types are missing specific members that exist at runtime (version mismatch, missing types), extend them:

// src/types/express.d.ts — add properties to Express's Request type
import { User } from '../models/User';

declare global {
  namespace Express {
    interface Request {
      user?: User;            // Added by passport.js or custom middleware
      sessionId?: string;
      startTime?: number;
    }
  }
}

// Must export something (even empty) to make this a module
export {};

Augment a specific package’s module:

// src/types/vue.d.ts — add global properties to Vue component instances
import { ComponentCustomProperties } from 'vue';
import { Store } from 'vuex';
import { Router } from 'vue-router';

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $store: Store<State>;
    $router: Router;
    $filters: {
      formatDate: (date: Date) => string;
      formatCurrency: (amount: number) => string;
    };
  }
}

export {};

Augment an npm package’s exported types:

// src/types/axios.d.ts — extend Axios request config
declare module 'axios' {
  interface AxiosRequestConfig {
    _retry?: boolean;      // Custom flag for retry logic
    _skipAuth?: boolean;   // Skip auth header on this request
  }
}

export {};

Fix 6: Handle JSON and Asset Imports

TypeScript does not know the types of JSON files or asset imports without configuration:

// Import JSON files
// tsconfig.json — enable resolveJsonModule
{
  "compilerOptions": {
    "resolveJsonModule": true
  }
}

// Now TypeScript infers the type from the JSON structure
import config from './config.json';
console.log(config.apiUrl);  // Typed correctly

CSS Modules:

// src/types/css-modules.d.ts
declare module '*.module.css' {
  const styles: Record<string, string>;
  export default styles;
}

declare module '*.module.scss' {
  const styles: Record<string, string>;
  export default styles;
}

Image and file imports:

// src/types/assets.d.ts
declare module '*.png' {
  const url: string;
  export default url;
}

declare module '*.svg' {
  import React from 'react';
  const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
  export { ReactComponent };
  const url: string;
  export default url;
}

declare module '*.jpg' {
  const url: string;
  export default url;
}

declare module '*.webp' {
  const url: string;
  export default url;
}

Environment variables in Vite:

// src/vite-env.d.ts (Vite creates this automatically — add your env vars)
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_APP_TITLE: string;
  readonly VITE_SENTRY_DSN?: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

Fix 7: Path Aliases in tsconfig

If you use path aliases (@/components/Button) and TypeScript cannot find the module, configure paths:

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@hooks/*": ["src/hooks/*"],
      "@utils/*": ["src/utils/*"],
      "@types/*": ["src/types/*"]
    }
  }
}

For bundlers, also configure the alias there (TypeScript paths only affect type-checking, not bundling):

// vite.config.ts
import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
});
// webpack.config.js
module.exports = {
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
};

Still Not Working?

Restart the TypeScript language server after any changes to .d.ts files or tsconfig.json. In VS Code: Ctrl+Shift+P then “TypeScript: Restart TS Server”.

Check if the .d.ts file is actually being picked up:

npx tsc --traceResolution 2>&1 | grep "some-library"
# Shows every file TypeScript checks when resolving the module

Triple-slash references — if a .d.ts file depends on other types, add a reference directive:

/// <reference types="node" />
/// <reference path="../other-types.d.ts" />

declare module 'my-module' {
  import { EventEmitter } from 'events';  // Uses Node.js types via reference
  export class MyEmitter extends EventEmitter {}
}

Version mismatch between @types and the library — if @types/foo is version 2.x but foo is version 3.x, there may be missing or incorrect types. Install the matching version:

npm install --save-dev @types/foo@3

Check the include and exclude arrays in tsconfig.json. If your .d.ts file is outside the include glob (for example, in a types/ directory at the project root but include only covers src/**/*), TypeScript will not see it. Either move the file inside the included path or extend the glob:

{
  "include": ["src/**/*", "types/**/*.d.ts"]
}

Verify the .d.ts file is not accidentally excluded by exclude. A common pattern is "exclude": ["node_modules", "dist", "**/*.test.ts"]. If your declaration file matches an exclude pattern (unlikely but possible with glob-heavy configs), it will be silently dropped.

Monorepo package resolution. In a monorepo with workspaces (npm, yarn, pnpm), TypeScript may not find types for sibling packages if the package’s types field points to unbuilt source. Ensure sibling packages are built before the consuming package runs tsc, or use TypeScript project references:

// tsconfig.json
{
  "references": [
    { "path": "../shared-lib" }
  ]
}

For related TypeScript errors, see Fix: TypeScript Type Not Assignable, Fix: TypeScript Cannot Find Module, Fix: TypeScript Path Alias Not Working, and Fix: TypeScript Enum Not Working.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles