"Exploring the world of Typescript declarations and the CommonJS module

I'm encountering confusion while creating declaration files (d.ts).

For instance, I have developed an NPM package called "a" with a single CommonJS module index.ts:

export interface IPoint {
    x: number;
    y: number;
}

export default function sub(one: IPoint, two: IPoint): IPoint {
    return {
        x: one.x - two.x,
        y: one.y - two.y
    };    
}

After compiling it, the generated a.d.ts looks like this:

export interface IPoint {
    x: number;
    y: number;
}
export default function sub(one: IPoint, two: IPoint): IPoint;

It seems that the compiler struggles to create valid d.ts for CommonJS. One must resort to utilities like dts-generator or manually wrapping:

declare module "a" 
{
    export interface IPoint {
        x: number;
        y: number;
    }
    export default function sub(one: IPoint, two: IPoint): IPoint;
}

Now, let's move on to developing package "b" which has a dependency on "a":

/// <reference path="node_modules/a/a.d.ts" />

import sub from "a"
import { IPoint } from "a"
export { IPoint }

export default function distance(one: IPoint, two: IPoint): number {
    var s = sub(one, two);
    return Math.sqrt(s.x * s.x + s.y * s.y);
}

So far, everything seems to be functioning correctly. Next, I aim to create a package "c" that depends on "b" (and so forth).

  1. How should I specify dependencies in the "b" module (link to "a.d.ts")? Should I try to specify them within "node_modules"? Or should I copy "a.d.ts" to the "/typings/" directory within the "b" package? And then copy "a.d.ts" and "b.d.ts" to "/typings/" in the "c" package (and beyond)?

  2. What is the significance of the "typings" section in "package.json"? In "b/package.json", I have written:

    "typings": "./b.d.ts"

This results in an error when compiling "c":

Exported external package typings file 'node_modules/b/b.d.ts' is not a module.
  1. How can I efficiently create d.ts files for CommonJS modules without having to manually write "declare module", "reference" statements, etc.?

Answer №1

It seems the compiler is unable to create valid d.ts files for CommonJS. One must use tools like dts-generator or manually wrap them:

However, this information is outdated (since version 1.6).

You can now simply compile module a by passing the declaration flag to tsc. The transpiler will automatically generate the declaration files for you.

Although these files are not external definition files, they serve as internal definitions.

Moreover,

Module b can easily locate and utilize these files if, in the package.json of module a, the typings entry points to the generated index.d.ts file

In summary:

For Module a:

  • compile with the declaration flag
  • update the typings entry to refer to the generated .d.ts file

For Module b:

  • simply import * as moduleA from 'a' or import {IPoint} from module 'a'

No need for cumbersome ///<reference= or manual typings anymore

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

Solutions for Utilizing Generic Mixins in Typescript

As a newcomer to Typescript, I have encountered an issue with mixins and generics. The problem became apparent when working on the following example: (Edit: I have incorporated Titian's answer into approach 2 and included setValue() to better showcas ...

A TypeScript class utilizing a static variable with the singleton design pattern

I have a query regarding the most effective way to code this scenario: Within a class, I require a static variable that is accessible throughout the entire project: connection Singleton without namespace: class Broker { static connection: Connection = u ...

How can I prevent the enter key from working with Twitter Typeahead?

Is there a way to prevent the enter key from being pressed on an element within Twitter Typeahead's dropdown feature while using Angular with Typescript? I attempted to utilize preventDefault() when event.keycode === 13 on the ng-keydown event for th ...

Caution in version 3.5.1 of Vue Router: The tag prop of `<router-link>` is now obsolete and has been eliminated in Vue Router 4

After updating the node packages of our Vue.js app, a warning is now appearing in the browser console: [vue-router] The 'tag' prop has been deprecated and removed in Vue Router 4. To remove this warning, use the v-slot API. Check out the migrat ...

Angular 2 forms, popping the chosen item in the `<select>` element

Check out the FormBuilder: let valuesArray = fb.array([ fb.group({ name: 'one' }), fb.group({ name: 'two' }), fb.group({ name: 'three' }), fb.group({ name: 'four' }) ]); this.for ...

What is the best approach to defining a type for a subclass (such as React.Component) in typescript?

Can someone help me with writing a type definition for react-highlight (class Highlightable)? I want to extend Highlightable and add custom functionality. The original Highlightable JS-class is a subclass of React.Component, so all the methods of React.Com ...

Strange activities observed during the management of state in react hooks, where the splice() function ends up eliminating the

My current setup involves maintaining a state to handle the addition of new JSX elements: const [display, setDisplay] = useState<IDisplay>({ BookingFormDropDown: [], } ); I have a function in onClick() which adds an elem ...

The data in the Angular variable is not persisting

After calling this function to retrieve an array of Articles, I noticed that the data is not being saved as expected. Take a look at my console output below. GetAll() { //return this.http.get<Array<Article>>(this.cfg.SERVER); this.http.get ...

Center a grid of cards on the page while keeping them aligned to the left

I have a grid of cards that I need to align in the center of the page and left within the grid, adjusting responsively to different screen sizes. For example, if there are 10 cards and only 4 can fit on a row due to screen size constraints, the first two ...

What sets apart calling an async function from within another async function? Are there any distinctions between the two methods?

Consider a scenario where I have a generic function designed to perform an upsert operation in a realmjs database: export const doAddLocalObject = async <T>( name: string, data: T ) => { // The client must provide the id if (!data._id) thr ...

The concept of TypeScript usage within the `mui-x` DataGrid while calling the `useGridApiRef()` function

Could someone please help me understand the syntax used in this code snippet from mui/mui-x? export declare const useGridApiRef: <Api extends GridApiCommon = GridApiPro>() => React.MutableRefObject<Api>; My interpretation is that it exports ...

TypeScript maintains the reference and preserves the equality of two objects

Retrieve the last element of an array, make changes to the object that received the value, but inadvertently modify the original last position as well, resulting in both objects being identical. const lunchVisit = plannedVisits[plannedVisits.length ...

Mastering the proper implementation of OneToMany and ManyToOne relationships in MongoDB involves understanding and utilizing the

I am currently working on setting up a oneToMany, ManyToOne relation method and here is my progress so far (pseudocode provided below). I am using Typegoose which is essentially Mongoose with types. If you are unfamiliar with it, that's okay because t ...

The intersection type of an array gets lost when used in the map() function

Running into an issue with my TypeScript code snippet where the mapped type is losing intersection type information inside the map(). type Foo = { foo: number }; type Bar = { bar: string }; const arr: Foo[] & Bar[] = [{ foo: 1, bar: 'bar' }] ...

Angular2- Retrieving configuration information during application launch

Implementing a method to load configuration data from an ASP.NET web API using HTTP at startup via APP_INITIALIZER. This approach was influenced by a discussion on Stack Overflow about loading configuration in Angular2 here and here. Snippet from app.modu ...

Having trouble integrating jQuery into an Angular CLI project

I'm trying to incorporate jQuery into my angular project created with angular cli. I followed the instructions provided on this website: To begin, I installed jQuery by running: npm install --save jquery; Next, I added type definitions for jQ ...

The function to increase the number of days on a date in Angular is experiencing technical issues

I'm facing an issue where I need to add 12 days to a specific date, but the new date is not coming out as expected. Below is the code snippet: addDays(days: number): any { let startDate = new Date(this.selectedDeliveryDate); let endDate = new ...

How do React Native proxies differ from vanilla React proxies in their functionality?

Trying to retrieve data from an API running locally on port 5000 of my device, I recalled setting the proxy in package.json when working on React web applications: "proxy": "https://localhost:5000" Attempting to fetch information f ...

Ways to access the chosen value from Ionic's popover modal

I have been working on a simple Ionic 4 Angular app and I am using an Ionic popover modal. The code below shows how I open the popover modal in my application: //home.page.ts async openModal(ev: Event) { const modal = await this.popoverController.create({ ...

Determine the data type of a parameter by referencing a prior parameter

Consider a scenario in my software where I have two distinct implementations of an Event Emitter. For instance: type HandlerA = (data: boolean) => void; type HandlerB = (data: number) => void; // HandlerB is somehow different from HandlerA type Eve ...