What is the best way to create and implement custom declaration files that are not available on @types or DefinitelyTyped?

I have encountered a situation where I am using an npm package named foo that is not available on DefinitelyTyped or may be outdated. Despite this, I still want to consume it under stricter settings like noImplicitAny, so I need to create custom definition files myself. My ultimate goal is to contribute these files to DefinitelyTyped for the benefit of others.

An easy solution is to create a global file called ./src/types.d.ts and define the module as follows:

declare module "foo" {
    export function hello(): void;
    export function world(): void;
}

However, using this syntax may require rewriting the module when submitting it to DefinitelyTyped. How can I organize my project in a way that allows me to easily author and submit local .d.ts files to DefinitelyTyped?

Answer №1

To help you out, I've broken down the process step-by-step with detailed explanations to make it easier to follow along. While it may seem like a lot of information, if you just stick to the provided instructions, it should only take a few minutes. Alternatively, you can use this shortened version that can be run in either bash or PowerShell!

mkdir -p ./local-types/foo
cd ./local-types/foo
npm init --scope types --yes
echo "export function hello(): void; export function world(): void" > ./index.d.ts
cd ../..
npm install ./local-types/foo

A Little Background

Imagine you have the following project structure:

proj/
├─ tsconfig.json
└─ src/
   └─ ...

Setting Up the Local Types Folder

You need to create a folder at the root of your project to store local types. It doesn't matter what you name it, but for now let's call it local-types. You can always rename it later once you're comfortable with the setup.

proj/
├─ tsconfig.json
├─ local-types/
└─ src/
   └─ ...

In most cases not covered by this example, you might want to name this folder types.

Creating a New Package in the Local Types Directory

If you are looking to import a module named foo, you'll need to create a folder called foo within the local types directory and include an index.d.ts file.

// local-types/foo/index.d.ts

export function hello(): void;

export function world(): void;

To turn this into an npm package, you also need to set up a package.json file:

cd local-types/foo
npm init --scope types --yes

At this point, your project structure should resemble the following:

proj/
├─ tsconfig.json
├─ local-types/
|  └─ foo/
|     └─ index.d.ts
|     └─ package.json
└─ src/
   └─ ...

You should now be able to import foo from any file within the src directory.

import { hello, world } from "foo";

hello();
world();

Keep in mind that if you don't have a single-entry-point package with an index.d.ts, you'll need to replicate the package structure as seen on npm.

Adding the Package as a Dependency

For libraries, consider adding this as a dependency, while applications may prefer devDependencies. Simply specify file:./local-types/foo as the version for @types/foo:

"dependencies": {
    "@types/foo": "file:local-types/foo"
}

Submitting to DefinitelyTyped

If your .d.ts files are complete and useful, think about writing tests and submitting a pull request to DefinitelyTyped so others can benefit as well!

If you can successfully import these packages without any runtime issues, then you've likely structured the package correctly.

Key Points to Remember

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

Guide on Implementing jQuery Plugin with Vue, Webpack, and Typescript

I am currently exploring the integration of the jQuery Plugin Chosen into my vue.js/Webpack project with TypeScript. After some research, I discovered that it is recommended to encapsulate the plugin within a custom Vue component. To kick things off, I m ...

Modifying the color of the chosen item - ion-select

Can anyone help me with changing the color of the selected item on ion-select? I've tried several solutions without success. Any suggestions? Documentation: https://ionicframework.com/docs/api/select I attempted to use the color property, but it did ...

Utilize AJAX or another advanced technology to refine a pre-existing list

I am trying to implement a searchable list of buttons on my website, but I haven't been able to find a solution that fits exactly what I have in mind. Currently, I have a list of buttons coded as inputs and I want to add a search field that will filte ...

Transferring JSON data through AJAX to a PHP backend

I have been working on a solution to convert a CSV file into JSON and then send it to BigCommerce using their REST API. Initially, I planned to use Javascript for the entire process, and everything was successful until I encountered issues with CORS when t ...

Retrieving subcollection data in Firestore using Angular

I am facing the challenge of extracting data from a subcollection within my database structure. Within my main collection products, there are documents that have a nested subcollection called reviews. products/prodID/reviews/reviewID Here is my interface ...

Securing special characters in cshtml

I am working on a razor view which includes a hidden field called Model.Token. The Token contains special characters that are then appended to a link in the href attribute. <a href='http://<a href="/cdn-cgi/l/email-protection" class="__cf_email ...

Using AngularJS to apply filters to JSON data

I'm having trouble filtering a JSON array. Here's an example of what my JSON array looks like: vm.users = [{ "fname": "Antoan", "lname": "Jonson", "Address": "Address1" }, ... ] How do I filter by last name starting with a specific term (e.g. & ...

How to customize the preview grid design in material-ui-dropzone

I am working on a book form page in my React app which includes an option to upload a cover photo. I opted for material-ui-dropzone from https://yuvaleros.github.io/material-ui-dropzone/ and it's working well, but I encountered an issue with the previ ...

Identifying and handling errors in the outer observable of an RXJS sequence to manage

Encountered a puzzling rxjs issue that has me stumped. Here's the scenario: I have two requests to handle: const obs1$ = this.http.get('route-1') const obs2$ = this.http.get('route-2') If obs1$ throws an error, I want to catch it ...

Typescript: Securing Data with the Crypto Module

I am currently working on encrypting a password using the built-in crypto module. Previously, I used createCipher which is now deprecated. I am wondering if there is still an effective way to achieve this. Here is the old code snippet: hashPassword(pass: ...

Using JQuery to modify several background images in unison

I have a CSS code that uses 8 images to create a frame: background-image: url(images/blue/tl.png), url(images/blue/tr.png), url(images/blue/bl.png), url(images/blue/br.png), url(images/blue/t.png),url(images/blue/b.png),url(images/blue/l.png),url(images/b ...

Using JavaScript to dynamically invoke a function and pass parameters dynamically

Exploring a dynamic method call with parameters in JavaScript. let obj = { method: 'foo1', params: ['one', 'two'] } foo1(p1, p2) { // do something } To execute it => [obj.method](obj.params) Is there a way to dyn ...

Using jQuery to access the ID of a div and create a custom close button

I am trying to implement a close button for my popup DIVs. Each one has a unique ID and I want to hide them by setting the CSS 'display' property to 'none' when closed. However, the following example is not functioning as expected. I a ...

Error TS2322: You cannot assign a Promise<any> to a string type

Having an issue in my react app where I am attempting to import the img source but encountering an error: TS2322: Type 'Promise<any>' is not assignable to type 'string'. What is the correct way to import an element into a variabl ...

What are the steps to fetch JSON data from a different domain server using AJAX?

I'm facing an issue with the API I'm using for my ajax call. It returns json and does not support jsonp, which unfortunately cannot be changed. Every time I try to use the code snippet below, I encounter a 'missing ; before statement' e ...

Error: The react.js application is unable to access the property 'classList' of a null object

I've encountered a bug that's been causing me some trouble. Every time I try to run my react application, I keep getting an error message that reads TypeError: Cannot read property 'classList' of null. As someone who is new to react, I& ...

Nextjs attempting to access local storage without proper initialization

I'm currently working on a feature where I have a sidebar with two buttons, contact and profile. When a user clicks on either of them, the URL updates to: /?section=clickedItem, allowing the user to save the state and return to that specific page upon ...

Refresh web content dynamically without having to reload the entire page using JavaScript

Currently, I am struggling to find a solution on how to dynamically update a section of a webpage using JavaScript when a user modifies an input field in another part of the same page. Unfortunately, my use of document.write is inhibiting me from making th ...

Unable to authenticate through LinkedIn

On my website, I am attempting to retrieve the user's first name, last name, and email using LinkedIn. Here is what I have done so far: In my LinkedIn App settings, under the Default Scope (OAuth User Agreement), I have selected the following options ...

Can you explain the functionality of this code snippet from a slate.js demonstration?

Trying to grasp the concepts of Slate.js, I delved into the rich text example. Within it, I encountered a code snippet that has left me puzzled. const isBlockActive = (editor, format) => { const [match] = Editor.nodes(editor, { match: n => ...