Exporting a constant as a default in TypeScript

We are currently developing a TypeScript library that will be published to our private NPM environment. The goal is for this library to be usable in TS, ES6, or ES5 projects.

Let's call the npm package foo. The main file of the library serves as an entry point and performs the following:

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

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

const foo = new Foo();

export default foo;

Our aim is to export both the main library class and have a default instance available for easy use by applications without the need to create a new one when not required.

In addition, we have created type definition files in a separate repository similar 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;
}

Unfortunately, running tests on the library results in an error message:

error TS1063: An export assignment cannot be used in a namespace.

The desired usage for the default instance should look like this:

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

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

foo.someMethod();

Are there any suggestions for correcting this issue?

UPDATE

Prior to @daniel-rosenwasser's suggestion, declaring just the module worked fine. However, a problem arose when attempting to create a new module that extended the initial one.

For example:

// 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 corresponding 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();
  }
}

This time, the errors received 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.

Answer №1

The error message shown is inaccurate, prompting me to create an issue for further investigation: https://github.com/Microsoft/TypeScript/issues/11092

In case you are working with ES-style modules, it is advisable to directly define them within the ambient module declaration like this:

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

    const foo: Foo;

    export default foo;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are the properties used in functional components of React?

Seeking guidance on passing React component props to another component: interface IMyComponent { props: Props<any> } const MyComponent: FC = ({ props }) => { } Previously, I attempted to utilize the React.Props type after consulting this que ...

Designing a TypeScript class with unique properties and attributes

I have an idea for creating a versatile class named Model. Here's what I have in mind: export class Model { _required_fields: Array<string> = []; _optional_fields?: Array<string> = []; constructor(params: Dictionary<string& ...

Unable to persist AWS CDK ec2.Instance userData configuration

Trying to launch an ec2 instance with AWS CDK has been successful, but I am struggling to make the userData persistent so it runs on every boot. Despite searching extensively, I couldn't find any documentation on how to achieve this. The code below wo ...

Tips for successfully sending an API request using tRPC and NextJS without encountering an error related to invalid hook calls

I am encountering an issue while attempting to send user input data to my tRPC API. Every time I try to send my query, I receive an error stating that React Hooks can only be used inside a function component. It seems that I cannot call tRPC's useQuer ...

Issues arise with the play method in Storybook and Jest when attempting to use the shouldHaveBeenCalled assertion on a

Here is a snippet of the component code: import { FC, ReactElement, useState, MouseEvent as ReactMouseEvent, ChangeEvent as ReactChangeEvent, } from 'react'; import { Stack, TablePagination } from '@mui/material'; export con ...

Is there a way to initiate validations for inputs within ReactiveForms?

After creating a form using Reactive Forms, I have implemented functionality for users to set a new password. The process involves entering both the old and new passwords, as well as confirming the new password. Throughout development, I considered the fol ...

Steps for converting TypeScript code to JavaScript using jQuery, without the need for extra libraries or frameworks like NPM

My single-page dashboard is quite basic, as it just displays weather updates and subway alerts. I usually refresh it on my local machine, and the structure looked like this: project/ index.html jquery-3.3.1.min.js script.js I decided to switch it t ...

Typescript: Shifting an image to the left and then returning it to the right

As a newcomer to Typescript, JavaScript, and front-end development, I am experimenting with creating a simulation of an AI opponent's "thinking" process when playing cards in a game. The idea is to visually represent the AI's decision-making by s ...

Implement new interface methods on-the-fly

I am seeking a way to dynamically incorporate methods that are defined in an interface. Initially, I considered using the index signature approach, but unfortunately, not all methods have the same signature. My objective is to preserve all type information ...

Display customizable template according to variable

The answer provided for the issue regarding dynamic template generation based on value instead of variable in this thread was really helpful. However, I'm facing challenges in getting it to work. Here's a simplified example: export class A { } ...

Exploring the TypeScript Type System: Challenges with Arrays Generated and Constant Assertions

I am currently grappling with a core comprehension issue regarding TypeScript, which is highlighted in the code snippet below. I am seeking clarification on why a generated array does not function as expected and if there is a potential solution to this pr ...

Guide on setting up a route in Next.js

Recently, I developed a simple feature that enables users to switch between languages on a webpage by adding the language code directly after the URL - i18n-next. Here's a snippet of how it functions: const [languages, ] = React.useState([{ langua ...

Custom "set attribute" feature in TypeScript

One issue I faced was resolved by creating the function shown below : function setProperty<T extends Record<string, string>>(obj: T, key: keyof T) { obj[key] = "hello"; } However, when I tried to compile the code, I encountered an ...

Leveraging functionality from an imported module - NestJS

Currently, I am utilizing a service from a services module within the main scaffolded app controller in NestJS. Although it is functioning as expected - with helloWorldsService.message displaying the appropriate greeting in the @Get method - I can't ...

Is there a way to remove trigger characters in vscode api completion function?

I am developing a vscode extension that requires custom completion for json files. I would like to know if it is possible to hide the trigger character when using autocompletions. Let me explain further : Imagine the trigger character is '.' In ...

What is the purpose of uploading the TypeScript declaration file to DefinitelyTyped for a JavaScript library?

After releasing two JavaScript libraries on npm, users have requested TypeScript type definitions for both. Despite not using TypeScript myself and having no plans to rewrite the libraries in TypeScript, I am interested in adding the type definition files ...

Event for changing Ionic 2 page

Is there a way to execute code every time the page changes without adding an ngOnDestroy method to every page in Ionic 2? Instead of using Ionic 2 page lifecycle hooks like ionViewDidUnload, is there a simpler solution by adding a single method to the mai ...

Need to import Vue component TWICE

My question is simple: why do I need to import the components twice in the code below for it to function properly? In my current restricted environment, I am unable to utilize Webpack, .vue Single File Components, or npm. Despite these limitations, I mana ...

Generate an alert with a numerical input field - Ionic

How can I create an input with type number in AlertController? I attempted to implement this, but the input only accepts text and not numbers. const alert = this.alertCtrl.create({ title: 'Add Ingredient', inputs: [ { name: ' ...

Encountering challenges with reusing modules in Angular2

I am currently working on an angular2 website with a root module and a sub level module. However, I have noticed that whatever modules I include in the root module must also be re-included in the sub level module, making them not truly reusable. This is w ...