Ambient Declarations & @types

An ambient declaration uses the declare keyword to describe the type of code that already exists at runtime — a global, a module, or an untyped library — without generating any JavaScript of its own.

Learn Ambient Declarations & @types in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

An ambient declaration is like a label on a sealed box . The box (a JavaScript global or untyped package) is already on the shelf; the label tells everyone what's inside without you having to open or build it. declare writes the label. @types packages are pre-printed labels the community made for the most common boxes, so you don't have to write them yourself.

1. The declare Keyword

The declare keyword introduces an ambient declaration: it states a value or function exists and what its type is, but produces no JavaScript. Use it to type a global a third-party script attaches to window , an analytics function, or anything your TypeScript references but doesn't itself create.

2. Declaring a Module for an Untyped Library

When you import a package that ships no types, TypeScript errors with "Could not find a declaration file". Fix it with {'declare module "name" '} in a .d.ts , describing just the parts you use. The same trick — with a wildcard like — types non-code imports such as images.

3. @types, DefinitelyTyped & Triple-Slash

For popular libraries you almost never write declarations by hand — the community publishes them on npm under the @types scope (from the DefinitelyTyped repo). Install the runtime package and its types separately: npm i lodash then npm i -D @types/lodash . A triple-slash directive like pulls another declaration set in.

🎯 Your Turn

Given the ambient declaration {'declare const config: '} , build the runtime object it describes. Fill in the blank marked ___ , then run it.

No blanks this time — just a brief and a starting outline. Build the object the ambient declaration describes, run it, and check your output against the example in the comments.

Practice quiz

What does the declare keyword do?

  • Generates JavaScript that creates the value
  • Imports a module at runtime
  • Tells the compiler something exists, emitting no JavaScript
  • Validates a value before use

Answer: Tells the compiler something exists, emitting no JavaScript. declare introduces an ambient declaration: it states a thing exists and its type, but produces no JavaScript output.

What does a .d.ts declaration file contain?

  • Only type information - no runtime code
  • Runtime code and types together
  • Compiled JavaScript
  • Just import statements

Answer: Only type information - no runtime code. A .d.ts file holds type information only; it describes the shape of existing JavaScript with no runtime code.

What is the risk of a declare that promises a global which isn't actually loaded?

  • A compile error
  • The global is created automatically
  • Nothing - declare guarantees existence
  • Type-checking passes but the program crashes at runtime

Answer: Type-checking passes but the program crashes at runtime. declare is a one-way promise that emits nothing. If the value isn't really there, checking passes but the code crashes at runtime.

How do you add types for an imported package that ships no types?

  • Rewrite the package in TypeScript
  • Use declare module "name" { export ... } in a .d.ts
  • Add a // @ts-ignore comment
  • Set strict to false

Answer: Use declare module "name" { export ... } in a .d.ts. declare module "name" { ... } in a .d.ts describes the parts of an untyped package you use, fixing the missing-declaration error.

What does a bare declare module "name"; with no body do?

  • Types the whole module as any - silencing the error with no safety
  • Errors at compile time
  • Generates stub functions
  • Imports the module's real types

Answer: Types the whole module as any - silencing the error with no safety. A bodyless declare module types the module as any: it silences the error but gives you zero type safety.

What is DefinitelyTyped?

  • A TypeScript compiler flag
  • A bundler for TypeScript
  • A community repository of declaration files published under @types on npm
  • A linting tool

Answer: A community repository of declaration files published under @types on npm. DefinitelyTyped is a community repo of .d.ts files for popular untyped libraries, published to npm under the @types scope.

After installing @types/lodash, what changes at runtime?

  • lodash runs faster
  • Nothing - @types adds only type information
  • lodash is recompiled
  • New functions are added to lodash

Answer: Nothing - @types adds only type information. @types packages add only .d.ts files; the runtime package is unchanged. Types are erased at compile time.

What does a triple-slash directive like /// <reference types="node" /> do?

  • Runs Node at compile time
  • Marks a file as a comment
  • Disables type checking for the file
  • Pulls in another declaration set or lib's ambient types

Answer: Pulls in another declaration set or lib's ambient types. A triple-slash reference directive includes another declaration file or library's ambient types into the current compilation.

Which wildcard module declaration is the standard way to type non-JS asset imports?

  • declare global { ... }
  • declare module "*.svg" { ... }
  • declare const assets: any
  • import type { Svg }

Answer: declare module "*.svg" { ... }. A wildcard like declare module "*.svg" types asset imports such as images in a typed build.

What should you NOT put in a .d.ts file?

  • Type aliases
  • interface definitions
  • Real runtime code
  • declare statements

Answer: Real runtime code. Declaration files are type-only; runtime code belongs in a .ts file. Use only declare, type, and interface in a .d.ts.