How to fix Ambient declaration 'X' cannot be declared in a non-ambient context in TypeScript
This error occurs when you try to use the 'declare' keyword in a regular .ts file instead of a .d.ts declaration file. Ambient declarations are type-only declarations that can only exist in .d.ts files or within declare namespace blocks.
Quick fix
Fixes Ambient declaration 'X' cannot be declared in a non-ambient context
// ❌ WRONG - in a regular .ts file
declare namespace MyNamespace {
interface MyInterface {
name: string;
}
}
export function doSomething() {
// implementation
}- Identify where the declare statement is located
- Move ambient declarations to a .d.ts file
- Separate types from implementations
- Use 'declare' only within appropriate blocks
// ❌ WRONG - in a regular .ts filedeclare namespace MyNamespace {interface MyInterface {name: string;}}export function doSomething() {// implementation}Ambient declaration 'X' cannot be declared in a non-ambient context
What this error means
This error indicates that TypeScript encountered an ambient declaration in a context where implementations are required. Ambient declarations are type-only declarations made with the `declare` keyword. They exist purely for the type system at compile-time and don't generate any JavaScript code. According to TypeScript's type system rules, ambient declarations can only appear in: 1. **Declaration files (.d.ts files)** - Files dedicated to type definitions 2. **Declare namespace blocks** - Inside `declare namespace { }` or `declare module { }` blocks 3. **Global scope of .d.ts files** - Top-level declarations When you use `declare` in a regular .ts file (which is a "non-ambient context" because it contains actual implementations), TypeScript throws this error because it doesn't know how to reconcile type-only declarations with executable code.
Typical symptoms
- TypeScript compiler error mentioning 'ambient declaration' and 'non-ambient context'
- Error appears when using 'declare' keyword in regular .ts files
- VS Code shows red squiggles under declare statements
- Build fails during compilation with error TS1039 or similar
- Error mentions specific identifiers that cannot be declared
- IDE cannot identify the declared types even though syntax looks correct
- Moving code between .ts and .d.ts files causes different error behavior
Common causes
- Using the 'declare' keyword in a .ts file instead of a .d.ts declaration file
- Trying to use 'declare' outside of a declare namespace or declare module block in .ts files
- Mixing ambient declarations with executable code in the same file
- Type definitions placed in implementation files rather than declaration files
- Incorrect file extension - .ts instead of .d.ts for pure type definitions
- Misunderstanding the purpose of declare keyword - it's only for types, not values
How to fix "Ambient declaration 'X' cannot be declared in a non-ambient context"
First, locate the problematic declare statement in your code:
// ❌ WRONG - in a regular .ts file
declare namespace MyNamespace {
interface MyInterface {
name: string;
}
}
export function doSomething() {
// implementation
}The error occurs because you're mixing declare (type-only) with executable code (export function) in the same file.
The primary solution is to move ambient declarations to a dedicated declaration file with the .d.ts extension:
Create a new file: src/types/my-namespace.d.ts
// ✅ CORRECT - in a .d.ts file
declare namespace MyNamespace {
interface MyInterface {
name: string;
}
function doSomething(): void;
}Declaration files (.d.ts) are treated as ambient contexts where declare statements are allowed and expected. They contain only type information without implementations.
Keep your .ts files for implementation code and .d.ts files for types:
File structure:
src/
├── types/
│ └── my-namespace.d.ts # Type definitions only
├── lib/
│ └── my-module.ts # Implementation code
└── index.tsExample separation:
my-namespace.d.ts:
declare namespace MyNamespace {
interface User {
id: string;
name: string;
}
function getUserById(id: string): User | null;
}my-module.ts:
namespace MyNamespace {
export interface User {
id: string;
name: string;
}
export function getUserById(id: string): User | null {
// implementation
return null;
}
}
export = MyNamespace;This clearly separates type declarations from executable code.
If you must use declare in a .ts file, wrap it in a declare namespace or declare module block:
// ✅ This is allowed - declare is inside a namespace block
declare namespace GlobalTypes {
interface Window {
customProperty: string;
}
}
// ✅ This is allowed - augmenting module types
declare module 'express' {
interface Request {
userId?: string;
}
}
// Implementation code can follow
export function setupMiddleware() {
// ...
}The declare statement creates an ambient (type-only) context within a limited scope, allowing it to coexist with implementation code.
If you need to both define types AND provide implementation, remove the declare keyword:
// ❌ WRONG
declare interface User {
name: string;
}
// ✅ CORRECT - no declare keyword
interface User {
name: string;
}
class UserClass implements User {
name: string = '';
}
export { User, UserClass };Only use declare when describing external types that are defined elsewhere. For your own types and implementations in .ts files, omit the declare keyword entirely.
Ensure your tsconfig.json is properly configured to include declaration files:
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"rootDir": "./src",
"typeRoots": ["./node_modules/@types", "./src/types"],
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}Key settings:
- typeRoots - Tells TypeScript where to find .d.ts files
- declaration: true - Generates .d.ts files from your TypeScript sources
- Include both .ts and .d.ts files in your includes/excludes
Advanced notes
### Understanding Ambient vs Non-Ambient Context
Ambient context refers to any code that exists purely in the type system without producing JavaScript runtime code. This includes:
- .d.ts files
- declare namespace blocks
- declare module blocks
- Global declare statements in .d.ts files
Non-ambient context refers to regular .ts files that produce JavaScript implementations.
### Common Patterns with Declare
Declaring global variables:
// ✅ In a .d.ts file or at top-level
declare global {
var globalVar: string;
}Extending external libraries:
// ✅ In a .d.ts file
declare module 'some-library' {
export interface SomeInterface {
newProperty: string;
}
}Ambient module federation:
// ✅ In a .d.ts file
declare module '*.json' {
const content: Record<string, unknown>;
export default content;
}### File Naming Conventions
- .d.ts - Declaration files (types only, no implementation)
- .ts - Implementation files (can include types but should not use declare at top level)
- .test.ts, .spec.ts - Test files (implementation)
### Common Migration Path
If you have a large .ts file with both types and implementations mixed with declare statements:
1. Create a corresponding .d.ts file with same base name
2. Move all declare statements there
3. Remove declare from the .ts file
4. The .ts file now contains only implementations with proper export statements
### TypeScript Version Considerations
This error handling has been consistent across TypeScript versions 3.x through 5.x. However, error messaging may vary slightly. Check your TypeScript version with:
tsc --versionIf upgrading TypeScript, re-run the compiler to get updated diagnostics.
Frequently asked questions
- What does "Ambient declaration 'X' cannot be declared in a non-ambient context" mean?
- This error indicates that TypeScript encountered an ambient declaration in a context where implementations are required. Ambient declarations are type-only declarations made with the declare keyword. They exist purely for the type system at compile-time and don't generate any JavaScript code.
- How do I fix "Ambient declaration 'X' cannot be declared in a non-ambient context"?
- This error occurs when you try to use the 'declare' keyword in a regular .ts file instead of a .d.ts declaration file. Ambient declarations are type-only declarations that can only exist in .d.ts files or within declare namespace blocks.
- What causes "Ambient declaration 'X' cannot be declared in a non-ambient context"?
- Using the 'declare' keyword in a .ts file instead of a .d.ts declaration file Trying to use 'declare' outside of a declare namespace or declare module block in .ts files Mixing ambient declarations with executable code in the same file
- Is the "Ambient declaration 'X' cannot be declared in a non-ambient context" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.