C.W.K.
Stream
Lesson 04 of 05 · published

Ambient Modules: `declare module`

~7 min · modules, ambient, declare

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"Ambient declarations describe something that exists, somewhere, without TypeScript knowing how."

What ambient means

'Ambient' is TypeScript's term for declarations that describe types without providing implementations. They tell the compiler 'this name exists and has this type; trust me on how it gets there.' The .d.ts files we covered are mostly composed of ambient declarations.

declare module — three forms

1. Standalone module declaration: declare module 'foo' in a .d.ts describes a module that's importable by name. We covered this in the previous lesson.

2. Wildcard module declarations: declare module '*.css' tells the compiler that any import ending in .css is fine and has a particular shape. Common pattern for CSS-modules or asset imports in bundler-based projects.

3. Augmenting existing modules: declare module 'react' { interface HTMLAttributes { custom: string } } adds a property to an existing module's interface. This is how library authors let you extend their types from outside.

Augmenting globals

The declare global block lets you augment the global scope. declare global { interface Window { myApp: ... } } adds a property to window everywhere in your project. Combined with interface declaration merging, this is how project-wide global types get added.

Ambient declarations are TypeScript's escape hatch for types-that-exist-somewhere. Wildcard, augmentation, and global declarations are how you bridge TypeScript's strict module model with the looser realities of bundlers, CSS imports, and library extensions.

Code

Ambient declarations — wildcards, augmentation, globals·typescript
// globals.d.ts — wildcard module declarations for bundler-aware imports.
declare module '*.css' {
  const content: { [className: string]: string };
  export default content;
}

declare module '*.svg' {
  const url: string;
  export default url;
}

// Now these imports compile:
import styles from './app.module.css';   // styles: { [className: string]: string }
import logo from './logo.svg';            // logo: string

// Augmenting an existing library's types.
declare module 'react' {
  interface CSSProperties {
    '--custom-var'?: string;             // allow CSS custom properties on style prop
  }
}

// Augmenting globals.
declare global {
  interface Window {
    __APP_VERSION__: string;
  }
}

window.__APP_VERSION__;   // ✅ typed

External links

Exercise

Set up wildcard declarations for .png (URL strings) and .json (an object). Import some of each from your code and confirm the types work. Why does Vite (or similar bundlers) already declare these for you?
Hint
Modern bundlers ship their own ambient declarations for asset imports. If you're using Vite, look in node_modules/vite/client.d.ts — you'll find a lot of wildcard module declarations there.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.