4

I have an interface that I only want to use within a namespace (internal module) and it should not be used outside the namespace.

Example interface:

namespace Test {
    interface IInterface {
        getId(): number;
        getName(): string;
    }
}

Unfortunately I get an error when I try to implement this interface within the same namespace if I don't export the interface (which I don't want to).

Implementing class:

namespace Test {
    class Implementer implements IInterface {
        private location: Location;

        public getId(): number {
            return 1;
        }

        public getName(): string {
            return "implementer name";
        }
    }
}

Which gives: TS2304: Cannot find name 'IInterface'. in 'Implementer.ts'.

Notice the private member of type 'Location' which is also a new type/class defined by myself in the same namespace and that is the actual reason for using namespaces because the type 'Location' already exists in the global space.

Class with conflicting name if used outside namespace:

namespace Test {
    class Location {
        private name: string = null;
        constructor(name: string) {
            this.name = name;
        }
    }
}

Additionally: I'm not using any modules and I'm converting some types from JavaScript to TypeScript classes. Using the /// <reference path="IInterface.ts" /> helper doesn't work (and is not the problem here). I also don't want to introduce any module loader.

So how do I use my interface in the same namespace without exporting it?

3
  • Maybe related: stackoverflow.com/questions/39827281/… Commented Oct 7, 2016 at 13:40
  • The other question doesn't mention internal interfaces or the accessibility of interfaces within names paces or modules Commented Oct 7, 2016 at 14:03
  • Yes, but if you start a new project, maybe you should consider to switch to modules. It's just a suggestion. :) Commented Oct 7, 2016 at 14:55

1 Answer 1

3

I answer first to the last question: "Class with conflicting name if used outside namespace". A global object Location already exists in the browser. You can use this name for your class in a module or in a namespace. Otherwise, you'll have to choose another name.

Then, you want to split a namespace. Just export the member IInterface in order to expose it outside the IIFE:

namespace Test {
    export interface IInterface {
        getId(): number;
        getName(): string;
    }
}

Explanation

From the handbook:

Namespaces are simply named JavaScript objects in the global namespace.

Here is an illustration (see the code in the TS Playground):

namespace Test {
  export let name = 'abc'
}

namespace Test {
  let message = 'Hello, ' + name;
}

After the compilation, here is the JavaScript code:

var Test;
(function (Test) {
    Test.name = 'abc';
})(Test || (Test = {}));

var Test;
(function (Test) {
    var message = 'Hello, ' + Test.name;
})(Test || (Test = {}));

The namespace Test is a "simply named JavaScript object in the global namespace". You can observe that the variable message couldn’t be reused outside its IIFE. Even if we create a third IIFE for the same global variable (namespace) Test.

Sign up to request clarification or add additional context in comments.

2 Comments

First export will make the interface accessible outside the namespace or module so that is unwanted. The problem of a name that already exists should not be handles by renaming my own object. Namespaces and modules are mainly there to solve this problem.
@Huupke, I added an explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.