Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to address internal module when a name conflict exists in TypeScript

In my TypeScript project (using only internal modules), I want to include polyfills/extension for an existing library. For this example, I will use the RxJS library but the question/problem is not specific to this library.

The following code is what I came up with:

module MyModule.Rx {
    Rx.Observable.prototype.myExtension = function() { /* ... */ };
}

The RxJS definitions (.d.ts files) are used and compiled together with the code. This leads to the following compiler error: 2339 Property 'Observable' does not exist on type 'typeof Rx'

As far as I can tell this happens because I used the same Rx identifier in MyModule.Rx. When switching the namespace in the first line to module MyModule.NotRx { everything works fine - the Observable type is correctly looked up from the RxJS .d.ts file.

So it seems that the names MyModule.Rx and the RxJS declared Rx namespaces are in conflict. I know that I could simply rename my namespace to MyModule.SomethingElse but that seems somewhat of a hack.

Having all polyfills/extensions for Rx in the MyModue.Rx namespace seems a natural choice for me - how can this be done in a clean way?

like image 316
Dynalon Avatar asked Oct 18 '25 11:10

Dynalon


2 Answers

You can't do that.

Take this code in TypeScript:

var B = 'test';
module A.B {
    // Declare a function
    export function fn() {
    }
    // Tests
    console.log(B); // Object {  }
    A.B.fn(); // valid
    B.fn(); // valid
    fn(); // valid
}

The message displayed in the console is: Object { } and not test. Look at the transpiled code:

var B = 'test'; // root scope
var A;
(function (A) {
    var B; // same name, hide the root scope one
    (function (B) {
        // Declare a function
        function fn() {
        }
        B.fn = fn;
        // Tests
        console.log(B); // Object {  }
        A.B.fn(); // valid
        B.fn(); // valid
        fn(); // valid
    })(B = A.B || (A.B = {}));
})(A || (A = {}));

The module A.B is transpiled to two JavaScript variables A and B. We can use them in order to access to the exported members of the module: the function fn is accessible from A.B.fn, B.fn and fn. In the module, the variable B from the root scope is hidden by the variable B of the module.

You can't access to a global variable Rx from a module named Rx.

like image 130
Paleo Avatar answered Oct 21 '25 03:10

Paleo


As mentioned by Tarh you cannot refer to an outer module if its been shadowed by a local variable. I've +1ed his answer and that should be the accepted answer. I'll just leave a few workarounds:

One workaround which you already know is to rename MyModule.Rx to something that doesn't have Rx. An alternative is to capture Rx with some other name:

import OrigRx = Rx;
module MyModule.Rx {
    OrigRx.Observable.prototype.myExtension = function() { /* ... */ };
}

This is very similar to https://stackoverflow.com/a/29021964/390330

like image 44
3 revsbasarat Avatar answered Oct 21 '25 03:10

3 revsbasarat