Fix TS2304: Cannot Find Name X TypeScript (2026)

TS2304: Cannot find name 'X' fires when TypeScript sees an identifier that is not declared anywhere it can see. Almost always caused by a missing import, missing @types/* package, or missing lib entry in tsconfig.json. Here is the complete 2026 fix guide.

Why TS2304 happens

TypeScript builds a scope of declared names. If your code references a name that is not in any scope (local variable, imported symbol, ambient declaration, or lib type), TS2304 fires. Fix by importing the name, installing the missing types package, or adding the appropriate lib.

Fix 1: missing import

// WRONG
function greet() {
  console.log(useState(0));
  // TS2304: Cannot find name 'useState'.
}

// FIX
import { useState } from "react";

function greet() {
  console.log(useState(0));
}

Fix 2: missing @types/* package

// WRONG in Node.js code
const port = process.env.PORT;
// TS2304: Cannot find name 'process'.

// FIX: install Node types
// pnpm add -D @types/node
// or: npm install --save-dev @types/node

// Then TS knows about process, Buffer, __dirname, etc.
const port = process.env.PORT;   // works

Common @types/* packages you may be missing:

  • @types/node for Node.js globals
  • @types/react for React APIs
  • @types/react-dom for ReactDOM APIs
  • @types/express for Express handlers
  • @types/lodash for lodash

Fix 3: missing DOM lib for browser globals

// WRONG (in a Node-only project)
const modal = document.querySelector(".modal");
// TS2304: Cannot find name 'document'.

// FIX: add DOM to tsconfig.json lib
// {
//   "compilerOptions": {
//     "lib": ["ES2022", "DOM", "DOM.Iterable"]
//   }
// }

Fix 4: missing globals declaration

// You use a global from an old script tag or bundled lib
console.log(analytics.trackEvent("view"));
// TS2304: Cannot find name 'analytics'.

// FIX: declare the global in a .d.ts file
// types/globals.d.ts
declare global {
  interface Window {
    analytics: {
      trackEvent(name: string): void;
    };
  }
  const analytics: {
    trackEvent(name: string): void;
  };
}
export {};   // required for global augmentation

// Now analytics is known
analytics.trackEvent("view");

Debugging checklist

  • Is the name a variable? Add an import.
  • Is it a Node.js API (process, Buffer)? Install @types/node.
  • Is it a browser API (document, window)? Add DOM to tsconfig.json lib.
  • Is it a third-party library? Install the library’s own types or @types/* package.
  • Is it a global your app injects? Declare it in a .d.ts file.

Real-world example: Node.js + browser hybrid

// tsconfig.json for a full-stack Next.js app
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],   // browser + modern JS
    "types": ["node"],                          // Node.js globals
    "moduleResolution": "bundler",
    "strict": true,
    "skipLibCheck": true
  }
}

// Now both fs (Node) and document (browser) are recognized
// depending on file context

Common mistakes when fixing TS2304

  • Installing the wrong @types/* package. Confirm the package name matches. Some libraries bundle their own types now.
  • Adding declare const without export {}. Global augmentation needs the empty export in the file.
  • Editing node_modules/@types directly. Gets overwritten. Use module augmentation in your own .d.ts.
  • Using @ts-ignore. Hides the error but leaves the runtime bug (if the global does not actually exist).

Debugging TypeScript errors systematically

TypeScript errors follow a predictable pattern once you understand the compiler’s logic. Before jumping to fixes, run through this diagnostic checklist.

  1. Read the FULL error message. The compiler tells you both the actual type it sees and the expected type. Match them side by side to spot the mismatch.
  2. Check strictNullChecks and strict mode. Many errors trace back to strict: true in tsconfig.json. If you inherited a codebase with strict mode on, expect more errors than in loose mode.
  3. Look at inferred types with hover. VS Code shows inferred types on hover. Compare what TypeScript sees vs what you assumed.
  4. Use // @ts-expect-error strategically. When you know better than the compiler temporarily, mark the line. TypeScript flags the annotation when the underlying issue is fixed.
  5. Isolate the failing line in a minimal reproducer. A standalone .ts file with hardcoded inputs often surfaces the root cause faster than debugging in place.

Common TypeScript configuration issues

Many “why does this not compile” issues trace back to tsconfig.json, not your code.

  • strict flag toggles many checks at once. strict: true enables strictNullChecks, noImplicitAny, strictFunctionTypes, and more. Turning on strict without preparing your code produces hundreds of errors.
  • Version mismatch between global and project TypeScript. Different TypeScript versions produce different errors. Pin the version in package.json for consistency.
  • skipLibCheck can hide real issues. Setting skipLibCheck: true speeds up compilation but hides type mismatches in dependencies. Fine for CI but keep it off during development.
  • Path aliases and moduleResolution mismatches. The paths config in tsconfig only works with the right moduleResolution setting. Match “bundler” for Vite, “node16” for Node.
  • Ambient declarations vs modules. Files with imports are modules; files without imports are ambient scripts. Some errors happen because a file is treated as one when you expected the other.

Production TypeScript best practices

Once you get past errors and ship code, keep these habits to prevent recurring problems.

  • Enable strict mode from day 1 on new projects. Migrating to strict later is 10x more work.
  • Never use any without a good reason. unknown is safer and forces you to narrow before use.
  • Avoid type assertions (as) except at API boundaries. Assertions bypass the type system. Use them sparingly at edges (JSON parsing, DOM, external APIs).
  • Prefer type over interface for new code. Type aliases work everywhere interfaces do, plus support unions, intersections, and mapped types.
  • Test type-level logic. Tools like expect-type or tsd let you write tests for your type definitions.

Learning resources for TypeScript

Beyond fixing the current error, deeper TypeScript knowledge pays dividends for years. Recommended starting points:

  • Official Handbook. typescriptlang.org/docs/handbook. The canonical reference, well-written and up-to-date.
  • Total TypeScript by Matt Pocock. Free tutorials and paid courses. Best for going from junior to advanced TypeScript.
  • Type Challenges GitHub repo. Interactive problems that build type-level programming skills.
  • TypeScript Deep Dive. Free online book, especially good for the “why” behind features.
  • Try in the playground. typescriptlang.org/play lets you experiment with types and see errors immediately.

TypeScript version considerations

Compiler errors can change slightly between TypeScript versions. TypeScript 5.0+ introduced better error messages for many common issues. If you are on 4.x, upgrading may automatically improve diagnostic quality without any code change. Check your package.json for the pinned typescript version, then compare against the release notes at github.com/microsoft/TypeScript/releases before upgrading in production.

Frequently Asked Questions

Why does @types/node fix so many errors?

Node.js exposes lots of globals (process, Buffer, __dirname). Without @types/node, TypeScript sees none of them. Almost every Node.js TS project needs this package.

Do I need DOM lib for React?

Yes for browser-rendered React. Server Components can skip DOM lib. Most Next.js starter tsconfigs include DOM by default.

What if the library has no @types/* package?

Write a minimal .d.ts in your project. Even declare module "some-lib"; silences TS2304 and TS7016 while you use the library.

Should I put custom types in a specific folder?

Convention is types/ or @types/ at project root. Make sure your tsconfig.json‘s include array covers it, or the compiler ignores the file.

Are TS2304 and TS2503 different?

TS2304 is any name, TS2503 is namespace-specific. Same fix approach: import the missing thing or declare it if truly ambient.

Leave a Comment