Generating ambient module declarations in Typescript for distribution on NPM

Seeking advice on generating TypeScript ambient module declarations for a node (commonjs) npm package being developed in TypeScript. Encountering confusion around the proper method to have TypeScript create these ambient module declarations for node / commonjs.

Our npm package is published as a scoped module, such as "@company/module". To ensure TypeScript can resolve the "scoped" module, it requires a fully qualified ambient module name declaration like "@company/module". However, we are unsure about the generation of named ambient modules and the correct way to generate ambient module declarations from the compiler.

Our module structure resembles the example below.

TypeScript

The code is compiled into index.js and bar.js respectively.

// ./bar.ts
export class Bar {} 

// ./index.ts
import { Bar } from "./bar"

export class Foo {
   constructor(private bar: Bar) {}
}

TypeScript Declaration

We aim to generate the following idealized output from the typescript compiler.

// ./index.d.ts

declare module "@company/module/bar" {
  export class Bar {}
}

declare module "@company/foo" {
  import { Bar } from "@company/module/bar"
  export class Foo {
    constructor(private bar: Bar)
  }
}

There doesn't seem to be a straightforward way to directly generate the above declaration from TypeScript. Our workaround involves:

  1. Compiling the declaration separately using module: AMD - outFile (emits declaration bundle and "ambient" declarations).
  2. Rewriting the compiled AMD declaration and prefixing declare module with "@company/module" (including the import).

There are ongoing github issues in the TS repository regarding generating bundled declarations in this manner, which are linked below.

Package declaration file for commonjs packages - (seems perfect) https://github.com/Microsoft/TypeScript/pull/3159

Proposal: Bundling TS module type definitions https://github.com/Microsoft/TypeScript/issues/4434

Interested in hearing others' experiences with publishing npm declaration files for TypeScript libraries on NPM. Open to all suggestions!

Thank you.

Answer №1

This is the anticipated result we hope to achieve using the typescript compiler.

There might not be a necessity for such an action, or at least there hasn't been any provided justification for it.

Your designated output directory like /module/bar should exhibit the following structure:

  • index.js < resulting .js for /module/bar.ts
  • index.d.ts < created .d.ts for /module/bar.ts

Whenever users call for @company/module/bar, the runtime mechanism resolves to .js, while TypeScript type system automatically resolves to .d.ts.

Instances

  • A multitude of TypeScript npm packages are available. Explore one of them here.
  • Get started with NodeJS quickly by referring to this guide.

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

Changing Image to Different File Type Using Angular

In my Angular Typescript project, I am currently working on modifying a method that uploads an image using the input element of type file. However, I no longer have an input element and instead have the image file stored in the assets folder of the project ...

How can I utilize an external file in Node js to output as a response?

I came across a similar inquiry, but I am interested in exploring manual methods. My goal is to achieve this without relying on express or any other external library. var http = require('http'); var server = http.createServer(function(req, res) ...

The current value of React.createRef() is perpetually empty

Ever since I started working on this code, I've been encountering a problem that seems to have no solution. Here's what's going on: import React, { Component } from 'react'; export class InfoPaneArrow extends Component<InfoPane ...

The method to create a global generic class in TypeScript

Is there a way to globally expose the Hash class? Access Playground here export {} class Hash<K, V> { } declare global { // How can we achieve this? } window.Hash = Hash // Making it globally accessible ...

Transform the process.env into <any> type using TypeScript

Need help with handling logging statements: log.info('docker.r2g run routine is waiting for exit signal from the user. The container id is:', chalk.bold(process.env.r2g_container_id)); log.info('to inspect the container, use:', chalk.b ...

Anticipating the resolution of promises and observables in Angular 2

Within my accountService module, there is a dialog prompt that requests the user's username and password, returning a promise. If the user clicks on close instead of dismissing the dialog box and the validators require the input data before allowing t ...

The render properties are not compatible with each other

I am currently using ReactQuill as a component, but I encounter this error when implementing it with Typescript. Do you have any suggestions on how to resolve this issue? The JSX element type 'ReactQuill' is not recognized as a constructor fun ...

Change number-type object fields to string representation

I am in the process of creating a function that takes an object as input and converts all number fields within that object to strings. My goal is for TypeScript to accurately infer the resulting object's fields and types, while also handling nested st ...

Command npm lacks a specified version. The .tool-versions file is not present

Currently, I am in the process of setting up my react app using VS Code. Upon successfully installing node.js (Version 18.12.1), I proceeded to run the command to create my app and encountered the following message: npm create-react-app example The npm c ...

Typescript fails to properly identify the yield keyword within a generator function or generator body

Here is the code for my generator function: function* generatorFunction(input: number[]): IterableIterator<number> { input.forEach((num) => { yield num; }); An error occurred during linting: A 'yield' expression is only allowed ...

Avoiding an endless spiral on a setter in JavaScript/TypeScript

Implementing TypeScript, I've been working on setting up a concept called a "trigger" : an object that includes both a checker function (which returns a Boolean) and a behavior function capable of performing various tasks. My aim is to execute the che ...

Navigating in express

Here is the structure I am working with: server.ts routes/ index.ts homeRoute.ts In server.ts: let app = Express(); app.use(router); In routes/index.ts: const routes = Router(); export default function router() { routes.use('/home' ...

Data string not being converted correctly to date format

Here is a table I am currently working with: ID DateColumn 1 3/7/2019 5:29:38 AM 2 3/8/2019 5:28:38 AM 3 3/7/2019 5:30:38 AM 4 3/7/2019 5:31:38 AM The date column in this table is being processed as a string when bound to the grid. To ...

When buttons are clicked within Angular Material's Card component, it automatically triggers the click event of the card itself

One of the challenges I'm facing is having a mat-card within a component template: <mat-card *ngFor="let p of products" (click)="viewProduct(p)"> <mat-card-actions> <button mat-stroked-button (click)="addProductToCart(p)"&g ...

NPM is having trouble locating a shell script

An error is encountered when running npm run build: '.' is not recognized as an internal or external command, operable program or batch file. Here is the npm file that contains relevant scripts: "scripts": { "postinstall": "jspm instal ...

What is the reason that {a: never} is not the same as never?

Is there a reason the code {a: never} cannot be simplified to just never? I believe this change would resolve the issues mentioned below. type A = {tag: 'A', value: number} type B = {tag: 'B', value: boolean} type N = {tag: never, valu ...

Troubleshooting a deletion request in Angular Http that is returning undefined within the MEAN stack

I need to remove the refresh token from the server when the user logs out. auth.service.ts deleteToken(refreshToken:any){ return this.http.delete(`${environment.baseUrl}/logout`, refreshToken).toPromise() } header.component.ts refreshToken = localS ...

Having trouble compiling the Electron App because of a parser error

Struggling to set up a basic electron app using Vue 3 and Typescript. Following the successful execution of certain commands: vue create app_name cd .\app_name\ vue add electron-builder npm run electron:serve Encountering issues when trying to i ...

Is there a way to easily toggle between a linked npm dependency during development and a separately installed dependency for staging or production environments?

I have been working on a unique npm module of my own with its GitHub repository. Simultaneously, I am developing a project that heavily relies on this custom module. To streamline the development process for the larger project, I find it beneficial to use ...

What is the best way to verify the input of a TextField element?

When I visited the Material UI Components documentation for TextField, I was hoping to find an example of validation in action. Unfortunately, all they showed was the appearance of the invalid TextField without any insight into the actual validation code i ...