ProgrammingFrontend Developer

What is a Namespace in TypeScript, what is it used for, and how does it differ from a module?

Pass interviews with Hintsage AI assistant

Answer.

Namespace is a mechanism for organizing code that emerged in the pre-ES6 era to group logically related entities together. It helps structure large projects by grouping classes, functions, interfaces, and types within a single namespace to avoid name conflicts and make the code more readable.

Historical context: Before the advent of JavaScript ES6 standards, developers used IIFEs, objects, and namespaces to simulate modularity. TypeScript introduced the namespace keyword (previously internal module) for grouping code.

Problem: Modern modules (ES6 Module) have become the standard, and both approaches (namespace and module) exist in parallel, which causes confusion in architectural design — when is it better to use a namespace, and when a module?

Solution: Namespaces are still useful for grouping utility functions and types in pure TypeScript projects (for example, when generating single JS files with outFile). To separate code across files, especially when working with npm and modern bundlers, it is more appropriate to use modules. Namespaces are often used in internal libraries, type declarations, and situations where structuring within a single file or in old code is necessary.

Example code:

namespace MyMath { export function add(a: number, b: number) { return a + b; } } console.log(MyMath.add(2, 3)); // 5

Key features:

  • Allows grouping logically related code
  • Can contain classes, types, functions, constants
  • Used with the outFile option, rarely in modern projects with modules

Tricky questions.

If you merge namespaces from different files, will it be one namespace or several?

TypeScript performs declaration merging — when names match, different parts of the namespace are merged into one if correctly connected and in the same scope.

// mathA.ts namespace MathUtil { export function sum(a: number, b: number) { return a + b; } } // mathB.ts namespace MathUtil { export function mul(a: number, b: number) { return a * b; } } // After compilation, MathUtil contains both methods

Can you use import/require for namespace like for a module?

No, namespaces do not have default export/named export; they cannot be imported using the standard ES6 syntax. Namespace is a purely TypeScript concept that does not transpile to JavaScript modules.

Can you import values from a namespace into another file via import?

No, accessing a namespace from other files requires using a reference (/// <reference path="..." />) or compiling with outFile; importing via import is impossible.

Common mistakes and anti-patterns

  • Mixing namespaces and modules in one project
  • Trying to import a namespace as a module
  • Using namespaces for every small piece of code (fragmentation)

Real-life examples

Negative case

In an old project, the logic was divided into dozens of namespaces, with the same names appearing in several files, which sometimes led to unexpected merging or conflicts. Transitioning to a modular architecture made code migration very labor-intensive.

Pros:

  • Quick grouping of functions
  • Simplicity for small scripts

Cons:

  • Confuses with real modules
  • Difficult to scale
  • Complexity in managing dependencies across files

Positive case

In a large library, an API was declared using namespace declarations in a single file index.d.ts, unifying all types and interfaces without implementation code. This enabled rapid typing for library consumers and simplified updating contracts between teams.

Pros:

  • Clear grouping of API
  • Simplicity in updating contracts

Cons:

  • More challenging to implement in new projects with modules
  • Not supported by npm autodescriptor