TypeScript TS2304: Cannot find name 'X'
Cannot find name
Verified against TypeScript docs: Compiler Errors, TypeScript handbook: Module Resolution, DefinitelyTyped repository · Updated May 2026
> quick_fix
TypeScript can't find a name in scope. Three causes: missing import, missing @types package, or wrong tsconfig.json 'lib' setting. Auto-import in your IDE usually fixes it; if not, install the @types package or add the global to tsconfig lib.
// Common: missing import
const result = useState(0) // TS2304: Cannot find name 'useState'
// Fix
import { useState } from 'react'
const result = useState(0)
// For globals like 'process', install @types/node
// pnpm add -D @types/nodeWhat causes this error
TS2304 fires when an identifier is referenced but TypeScript can't resolve it: it's not imported, not declared in the current scope, and not provided by any ambient declaration (lib.dom.d.ts, @types packages, or *.d.ts files in the project). The error says nothing about whether the name exists at runtime; it's purely a compile-time visibility check.
How to fix it
- 01
step 1
Add the missing import
Most TS2304 errors are missing imports. Use IDE auto-import (VS Code: Cmd+. on the underlined name). The compiler doesn't auto-import; your IDE adds the import statement.
// Before useState(0) // TS2304 // After import { useState } from 'react' useState(0) - 02
step 2
For Node.js globals, install @types/node
process, Buffer, __dirname, and other Node globals need @types/node. Without it, TypeScript doesn't know they exist.
pnpm add -D @types/node # Then process.env.X resolves correctly - 03
step 3
For browser APIs, check tsconfig.json lib
DOM types (window, document, fetch) come from lib.dom.d.ts. If your tsconfig has lib: ['ES2022'] without 'DOM', browser APIs are missing. Add 'DOM' for client code; remove for pure-Node code.
{ "compilerOptions": { "lib": ["ES2022", "DOM", "DOM.Iterable"] } } - 04
step 4
For declared globals (CSS modules, env vars), add a .d.ts
If you import CSS modules or use a custom global, declare them in a global.d.ts. The file gets picked up automatically as long as it's included in tsconfig.
// global.d.ts declare module '*.module.css' { const classes: { [key: string]: string } export default classes } // Custom global declare global { interface Window { myCustomGlobal: () => void } } export {} - 05
step 5
For library types in old libs, install @types separately
Many older libraries don't bundle types. Check if @types/<package> exists on npm. If not, write a stub .d.ts.
# Check if types exist npm view @types/lodash # Install pnpm add -D @types/lodash # If no @types package, stub it echo "declare module 'old-package';" > old-package.d.ts - 06
step 6
Check tsconfig include and exclude
If your file isn't included in tsconfig's 'include' list, IDE-level TS may resolve names but build-time tsc won't. Confirm your test files, scripts, etc. are in include.
{ "include": ["src/**/*", "app/**/*", "types/**/*"], "exclude": ["node_modules", "dist"] }
Why TS2304 happens at the runtime level
TypeScript's name resolver in src/compiler/checker.ts resolves identifiers via lexical scope: parameters, local declarations, imported names, then ambient declarations from .d.ts files in the project. The lib option in tsconfig.json determines which built-in declarations are loaded (lib.dom.d.ts for browser APIs, lib.es2022.d.ts for modern ECMAScript). The types option restricts which @types packages from node_modules/@types are auto-loaded. When a name reference reaches the resolver and no scope contains a binding, TS2304 fires. The same lookup also feeds the 'Did you mean X?' suggestion in TS2552 when a similar name is found.
Common debug mistakes for TS2304
- Forgetting to add a new dependency to package.json after copy-pasting a code sample.
- Using process.env without @types/node installed.
- Configuring tsconfig with 'lib': ['ES2022'] but using fetch, document, or window in client code.
- Adding @types/jest but not adding 'jest' to compilerOptions.types when types is already restricted.
- Declaring globals in a .d.ts file that's not included by tsconfig (typo in include/exclude paths).
When TS2304 signals a deeper problem
Recurring TS2304 errors signal that the project's type-discovery configuration is incomplete. The architectural fix is to standardize tsconfig per environment: client tsconfig with 'DOM' lib, server tsconfig with 'node' types, test tsconfig with jest/vitest types. Use tsconfig 'references' to compose them in monorepos. Write a single global.d.ts for genuinely-global declarations (CSS modules, image imports, env vars) and include it everywhere. With this, IDE and tsc agree on what's in scope, and TS2304 fires only on actual missing imports the IDE can auto-fix.
Frequently asked questions
What's the difference between TS2304 and TS2552?
TS2304 means the name doesn't exist anywhere TypeScript can see. TS2552 means TypeScript thinks you typoed and suggests a similar name in scope ('Did you mean useEffect?'). TS2552 is TS2304 plus a hint. Both fix the same way: add an import, install types, or correct the typo. The IDE shows TS2552 more often than the bare TS2304 because suggestion-mode is on by default.
Why does my IDE find the name but tsc doesn't?
Your IDE may use a different tsconfig.json than the one tsc reads. Common in monorepos with nested tsconfigs. Check which tsconfig your build uses: tsc --showConfig prints the resolved config. The IDE's TypeScript Server picks up the nearest tsconfig walking up from the file; tsc uses the explicit --project flag or the nearest tsconfig from CWD. Make sure both find the same config and that 'include' covers your file.
Why does jest's 'describe' or 'it' show TS2304?
Jest's globals (describe, it, expect, beforeEach) need @types/jest installed and 'jest' added to tsconfig's 'types' field. Without it, the testing globals are undeclared. Install @types/jest and add: { compilerOptions: { types: ['jest', 'node'] } }. Note 'types' is restrictive: when set, only listed types packages are loaded, not all of @types. If you need every package, omit 'types' entirely.
Should I declare an ambient global to silence TS2304?
Only if there's a real runtime global. Declaring 'declare const myFn: any' silences the error but doesn't make the function exist - if it's not actually defined at runtime, you crash. Common legitimate cases: env vars injected by Vite/Webpack, browser APIs in a Cloudflare Worker, custom Window properties. For each, write a precise type in global.d.ts. Avoid 'any' - it defeats the purpose of having TypeScript at all.