Typescript: Provide a way to alias namespaces

Created on 6 Aug 2016  ·  15Comments  ·  Source: microsoft/TypeScript

TypeScript should have a way to embed (type) namespaces. In the following case, assigned (embeded) namespace NS.A should have a C type.

TypeScript Version: master

Code

namespace NS_A {
  export class C {
  }
}
namespace NS {
  export var A = NS_A;
  export type A = NS_A;
}
var C = NS.A.C;
type C = NS.A.C;

Expected behavior:

$ node built/local/tsc.js --lib es6 -m commonjs --noEmit index.ts

Actual behavior:

$ node built/local/tsc.js --lib es6 -m commonjs --noEmit index.ts
index.ts(7,19): error TS2304: Cannot find name 'NS_A'.
index.ts(10,13): error TS2305: Module 'NS' has no exported member 'A'.
Needs More Info Suggestion

Most helpful comment

I've been thinking about this as well. We have var / const to alias a value, and type to alias a type, but no equivalent for namespace. We could even consider

namespace ns = foo;

for establishing namespace aliases.

All 15 comments

I've been thinking about this as well. We have var / const to alias a value, and type to alias a type, but no equivalent for namespace. We could even consider

namespace ns = foo;

for establishing namespace aliases.

Thanks!! I agree its syntax.

related: #5220

When extending namespaces, namespace merging is not good for immutability.

namespace ns = foo;
// foo is overwritten
namespace ns {
  export var bar;
}

Source namespaces shouldn't be changed by another module. So I think, an extends keyword for namespaces is a good solution.

// foo is not overwritten
namespace ns extends foo {
  export var bar;
}

It seems this existing syntax just works?

namespace NS_A {
  export class C {
  }
}
namespace NS {
  export import A = NS_A;
}
var C = NS.A.C;
type C = NS.A.C;

why won't we unify objects and namespaces instead of making them even more separated without a good reason?

related #8358

@SaschaNaz Oh, I didn't know its syntax. My problems were solved. Thanks for the great answer!!

as was shown it works fine as long as you separate values/functions from types, unifying them is what we all can benefit from

Looking to understand what the use cases for this are. Some real world code examples would be useful.

11025 is also a good use case

To explain what's going on in #11025 -- there's no way to alias in the namespace side of an elided module import into a merged identifier.

@RyanCavanaugh I know this is pretty old, but I'm currently trying to create better type defs for the popular node-forge library, which does a bunch of aliasing. E.g.:

forge.pki = forge.pki || {};
module.exports = forge.pki.rsa = forge.rsa = forge.rsa || {};

Thus, I'm looking to do something where I can alias like:

declare module 'node-forge' {
  namespace pki {
    namespace rsa {
      interface GenerateKeyPairOptions {}
      generateKeyPair(opts?: GenerateKeyPairOptions): KeyPair;
    }
  }
  // What I'd like to do:
  // namespace rsa = pki.rsa;

  // What I've tried:
  const rsa = pki.rsa; // Access to values from namespace
  type rsa = pki.rsa; // Trying to alias as type to access types (doesn't work)
}

When using this lib, I should be able to do the following, but can't access types:

import {rsa} from 'node-forge';

// TS2503: Cannot find namespace 'rsa'
const opts: rsa.GenerateKeyPairOptions = {};

// Works fine as aliased value
rsa.generateKeyPair(); 

I have a similar use case that involves nested namespaces:

// index.d.ts
declare namespace Parent {

}

// other.d.ts
declare namespace Other {
  // exported members
}

I'd like to expose everything in Other as a nested namespace of Parent. Something like:

declare namespace Parent {
  namespace Child = Other;
}

Today I achieve this by individually re-exporting the members of Other:

// index.d.ts

import {Other} from './other';

declare namespace Parent {
  namespace Child {
    export import Member1 = Other.Member1;
    export import Member2 = Other.Member2;
    // and so on...
  }
}

stumbled upon this issue, it looks like this feature is supported now
see doc here https://www.typescriptlang.org/docs/handbook/namespaces.html#aliases
@falsandtru if that answer your question you might want to close this issue

Was this page helpful?
0 / 5 - 0 ratings