TL;DR โ Quick Fix
Drop an empty export {} at the top of your file. That single line turns it into an ES module and kills the conflict with TypeScript's built-in DOM globals.
// Add this at the top of the file
export {};
const name = 'John';
The Error
Cannot redeclare block-scoped variable 'name'.
You write const name = 'John' โ a perfectly normal declaration. TypeScript screams. There's no other name in your file. Nothing looks wrong. Yet the red squiggly appears immediately.
Root Cause
A .ts file with no import or export statements is treated by TypeScript as a global script, not an ES module. That means your local variables share scope with TypeScript's built-in type declarations.
Deep inside lib.dom.d.ts, TypeScript ships this:
// Inside lib.dom.d.ts (TypeScript's built-in)
declare var name: string;
Your const name runs straight into that declaration. Common culprits that trigger this clash:
nameโwindow.namedocumentโwindow.documentlocationโwindow.locationeventโwindow.eventstatusโwindow.statusoriginโwindow.origin
Fix Approaches
Option 1: Add export {} to the file (Recommended)
One line. No side effects. An empty export tells TypeScript this file is a module, so it gets its own isolated scope.
// At the very top of your file
export {};
const name = 'Alice';
const location = 'Tokyo';
console.log(name, location);
Everything below stays untouched. This is the go-to fix for browser apps, React/Vue/Angular projects โ anything that touches the DOM.
Option 2: Remove lib.dom from tsconfig (Node.js only)
Building a CLI tool or a backend script? You probably don't need DOM types at all. Strip dom from the lib array:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"]
}
}
Without dom, TypeScript never loads lib.dom.d.ts, so name, document, and friends simply don't exist as globals anymore.
Warning: Never do this in a React, Vue, or Angular project. Removing dom breaks all browser API types instantly.
Option 3: Rename the conflicting variable
Sometimes the fastest path forward is a rename. Pick something that doesn't collide:
// Before (conflicts with window.name)
const name = getUserName();
// After
const userName = getUserName();
const displayName = getUserName();
Works fine for new code. Less appealing when you're knee-deep in a refactor and touching a variable used in 40 places.
Option 4: Enable isolatedModules in tsconfig
Running Vite, esbuild, or Babel? These bundlers transpile each file independently โ and isolatedModules: true aligns TypeScript's behavior to match:
{
"compilerOptions": {
"isolatedModules": true,
"target": "ESNext",
"module": "ESNext"
}
}
With this flag on, TypeScript will warn you whenever a file has no imports or exports and isn't explicitly a module. You catch the problem at the source instead of chasing the symptom.
Option 5: Wrap code in a block scope or IIFE
Running a quick throwaway script with ts-node? Adding an export might feel overkill. A block scope or IIFE works just as well:
// Block scope
{
const name = 'Bob';
console.log(name);
}
// Or IIFE
(function () {
const name = 'Bob';
console.log(name);
})();
It does the job. It's just less idiomatic than export {} for anything beyond a one-off script.
Verifying the Fix
Run the TypeScript compiler in check-only mode โ no output files, just errors:
# Run the TypeScript compiler with no-emit to check for errors only
npx tsc --noEmit
# Or if you have tsc installed globally
tsc --noEmit
Clean output means clean code. In VS Code, the red squiggly should disappear the moment you save the file โ no restart needed.
Why This Happens More Often in New Files
Fresh .ts file, no imports yet โ you're in global script mode from the first keystroke. The second you add a real import (say, pulling in a utility from another file), TypeScript quietly switches the file to ES module mode and the conflict vanishes on its own.
That's why this error tends to cluster around:
- Standalone utility scripts with no imports
- TypeScript config files
- Quick snippets you're experimenting with in isolation
- Files where all imports were stripped out during a recent refactor
Summary
SituationBest Fix
Browser / React / Vue appAdd `export {}` to the file
Node.js / CLI toolRemove `dom` from `lib` in tsconfig
Vite / esbuild projectEnable `isolatedModules: true`
Quick script, no module neededWrap in a block scope `{ }`

