Fix: TypeScript Could Not Find Declaration File — Module Has No Type Information
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:
- Bundled types —
typesortypingsfield in the module’spackage.json(included by the package itself) - DefinitelyTyped —
@types/<package-name>innode_modules/@types/ - Type roots in
tsconfig.jsontypeRootsfield - Declaration files —
.d.tsfiles 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
@typespackage exists — many smaller or newer packages do not have community-maintained types - Types package not installed — the
@typespackage exists but was not installed - Package has
exportsmap withouttypescondition — modern packages usingexportsinpackage.jsonneed atypescondition for each export path; without it, TypeScript cannot find subpath types moduleResolutionsetting mismatch — packages usingexportsfields require"moduleResolution": "bundler"or"node16", not the older"node"mode- Local file has wrong extension — importing
./configexpectsconfig.tsorconfig.d.tsto exist typeRootsortypesin tsconfig excludes the declaration — settingtypeRootsreplaces the default lookup; settingtypeswhitelists 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/multerFind if an @types package exists:
npm search @types/package-name
# Or check the TypeScript registry
# https://www.typescriptlang.org/dt/searchAfter installing, verify TypeScript finds the types:
npx tsc --noEmit # Should compile without the error nowFix 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
anytypes) 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
typeRootswithout including./node_modules/@types. When you settypeRoots, it completely replaces the default behavior. If you only set"typeRoots": ["./src/types"], TypeScript stops looking innode_modules/@typesentirely, which breaks@types/node,@types/react, and every other@typespackage.
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.tsFix 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 pathFix 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 correctlyCSS 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 moduleTriple-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@3Check 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.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: pdf-lib Not Working — PDF Not Generating, Fonts Not Embedding, or Pages Blank
How to fix pdf-lib issues — creating PDFs from scratch, modifying existing PDFs, embedding fonts and images, form filling, merging documents, and browser and Node.js usage.
Fix: Pusher Not Working — Events Not Received, Channel Auth Failing, or Connection Dropping
How to fix Pusher real-time issues — client and server setup, channel types, presence channels, authentication endpoints, event binding, connection management, and React integration.
Fix: date-fns Not Working — Wrong Timezone Output, Invalid Date, or Locale Not Applied
How to fix date-fns issues — timezone handling with date-fns-tz, parseISO vs new Date, locale import and configuration, DST edge cases, v3 ESM migration, and common format pattern mistakes.
Fix: Zod Validation Not Working — safeParse Returns Wrong Error, transform Breaks Type, or discriminatedUnion Fails
How to fix Zod schema validation issues — parse vs safeParse, transform and preprocess, refine for cross-field validation, discriminatedUnion, error formatting, and common schema mistakes.