2

We have a TypeScript library that we are publishing to a private NPM environment and we want to use that library in other TS, ES6 or ES5 projects.

Let the library be an npm package named foo, its main file works as a barrel doing the following:

// Index.ts
import Foo from './Core/Foo';

export {default as Foo} from './Core/Foo';

const foo = new Foo();

export default foo;

We want to export the main library class as well as a default instance for apps to use it without creating a new one unless necessary.

Also, we created the type definition files in a separate repository in a similar way to DefinitelyTyped:

// foo.d.ts
declare namespace Foo {
  export class Foo {
    public constructor()
    // ...methods
  }

  const foo: Foo;

  export default foo;
}

declare module 'foo' {
  export = Foo;
}

Running the tests for it fails with error TS1063: An export assignment cannot be used in a namespace.

What I'm aiming for is to have the usage of the default instance like this:

// ES5, browser env
window.Foo.foo.someMethod();

// ES6/TS
import foo from 'foo';

foo.someMethod();

Any ideas if there is a right way to do this?

EDIT

Declaring just the module as @daniel-rosenwasser suggested worked before, but there was a problem when we tried to create a new module that extended the first.

For instance:

// bar.d.ts
/// <reference path="../foo/foo.d.ts"/>

import {
  Foo
} from 'foo';

declare module 'bar' {
  export class Bar extends Foo {
    public constructor();
    // more methods
  }
}

And its tests:

// bar-tests.ts
/// <reference path="../foo/foo.d.ts"/>
/// <reference path="./bar.d.ts"/>

import foo, {
  Foo
} from 'foo';

import {
  Bar
} from 'bar';

namespace TestBar {
  {
    let result: Foo;
    result = foo;
  }

  {
    let result: Foo;
    result = new Bar();
  }
}

The errors this time are:

bar/bar-tests.ts: error TS2307: Cannot find module 'bar'.
bar/bar.d.ts: error TS2664: Invalid module name in augmentation, module 'bar' cannot be found.
1

1 Answer 1

4

The error message here is wrong, so I opened up an issue for you: https://github.com/Microsoft/TypeScript/issues/11092

If you have an ES-style module, you should define it directly in the ambient module declaration:

declare module "foo" {
    export class Foo {
        public constructor()
        // ...methods
    }

    const foo: Foo;

    export default foo;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Yes, this is pretty much what I had before, but the problem came later when I tried to create a new module that extends this one, will add the sample to the question...
When in another module, the declare module "foo" {} syntax creates a module augmentation. The reason that you're in another module is that you have a top-level import. You can move the import into the declare module "bar"` to make it work correctly.
This worked! I did not realize the import statements should go inside the module declaration, thanks Daniel!

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.