Skip to content
Advertisement

Difference between classes and namespaces in TypeScript

What is exactly the difference between classes and namespaces in TypeScript? I know that if you create a class with static methods you can access them without instantiating the class and that is exactly one of the points of namespaces I guess.

I also know that you can create more than one Namespace with the same name and their methods will belong to the same function when compiled to JS.

But I can’t figure out when to use one or another…for me, at the end, classes and namespaces are almost the same, so I guess I am missing something…

Advertisement

Answer

You’re right. Namespaces and static classes are similar. They have some common features. They are both syntactical sugar of ES5 patterns that share similarities – cf. transpiled JavaScript given by the TypeScript playground:

// TypeScript
class C {
    static readonly Name = 'C';
    static print() {
        console.log(`Name=${C.Name}`);
    }
}

namespace N {
    export const Name = 'N';
    export function print() {
        console.log(`Name=${Name}`);
    }
}

// Usage
C.print();
N.print();
const c = new C();
const n = new N(); // TS Error: Cannot use 'new' with an expression whose type lacks a call or a construct signature

// Transpiled JavaScript
var C = /** @class */ (function () {
    function C() {
    }
    C.print = function () {
        console.log("Name=" + C.Name);
    };
    C.Name = 'C';
    return C;
}());

var N;
(function (N) {
    N.Name = 'N';
    function print() {
        console.log("Name=" + N.Name);
    }
    N.print = print;
})(N || (N = {}));

Yet, they have also their own features:

  • Namespaces are only in TypeScript and not in ECMAScript. They can be seen as IIFE syntactical sugar. They can be nested (e.g. A.B.C) to resemble C# namespaces. Since ECMAScript 6 (ES6/ES2015), in most cases ES6 modules are more interesting than namespaces because it’s simpler to handle nesting at the file level and keep the code structure flat.

  • Classes including static members are also available in ES6. They are also syntactical sugar of the “constructor function pattern”. A static class offers the same features as a namespace but with a syntax less usual – see the previous example.

So fundamentally each pattern has its own philosophy related to these use cases:

  • For static (i.e. +/- global) members: ES6 modules in most cases; TypeScript namespaces sometimes, even inside a module – see TS Doc; or just a constant object literal,
  • To create object: classes (that can have static members too by the way, like factory methods), factory functions, just plain object literals, …

These suggestions can help produce code more “idiomatic” i.e. easier to read and to maintain.

But you / your team own your code and the decision is yours. You may try different patterns to compare them based on your experience. Finally, if it’s your choice, using pure static classes over namespaces is not bad, like using namespaces instead of ES6 modules.

Advertisement