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

The essential criteria for script tag and page validation requirements

There are instances where I have pages that contain only a script without any content (such as sending data through postMessage and then closing itself). In these cases, is the page considered valid with just <script>doSomeStuff</script> or do ...

Ways to append multiple values to an object ID in mongoDB at a later time

I have a pre-existing object ID in my MongoDB database, and I am looking to add more values inside it in the future. Here is an example of my current MongoDB structure: [{ label: 'colors', options: [ { label: 'Bl ...

Encountering an issue with NPM while attempting to install Parcel

After trying multiple solutions from various online sources, I am still unable to resolve the issue. Any advice or recommendations would be highly appreciated! npm ERR! code 1 npm ERR! path C:\Users\Tarun\Desktop\NamasteReact\node_ ...

Even though my form allows submission of invalid data, my validation process remains effective and accurate

Here is the code I have written: <!doctype html> <html lang="en"> <head> <title>Testing form input</title> <style type="text/css></style> <script type="text/javascript" src="validation.js"></script> &l ...

Microsoft Edge browser incorrectly calculates range.endOffset value

This particular problem is specific to the Microsoft Edge browser. I am attempting to apply a CSS style to a selected word using Range API's, but I am encountering an issue with the range.endOffset functionality in Edge. Below is the code snippet I am ...

Put an end to the endless game of defining TypeScript between Aurelia CLI and Visual Studio 2017 builds

I am encountering TypeScript errors in my Visual Studio build for an Aurelia project within a .NET Core project. The errors include 'Build:Cannot find name 'RequestInit'', 'Build:Cannot find name 'Request'', and &apo ...

Prevent repeating the same table header multiple times when generated dynamically with jQuery

I have an array called groups which contains name and regid. I want to display the name key as the column header of a table. To achieve this, I implemented the following code: var Name = v.name; var regId = v.regid; var rowStr = '<th d ...

Experiencing issues with obtaining req.params.id undefined while initiating a put request

Encountering an issue while making a PUT request using Postman, as an error occurs in the VSCode terminal with the message: let product = await Product.findById(req.params.id); ^ TypeError: Cannot read property 'id' of undefined. The request ...

What could be causing my Chrome extension to function on Mac but not on a PC?

I created a basic Chrome extension that includes a background page with the following code: <script type="text/javascript> chrome.tabs.onDetached.addListener(function(tabId, info){ var id = tabId; chrome.tabs.get(id, function(tab) { ...

Attributes for 'v-bind' directives must have a value specified

Struggling to implement a tree structure in vue.js and encountering an issue with element props. Any assistance would be greatly appreciated. I've attempted using :content="{{tempCont}}" as well as content="{{tempCont}}", but neither approach proved ...

Guide to inserting text into an html element upon clicking an ASP:Button

In my code, there is a DIV that holds some text. Accompanying the text is an asp:Button. When this button is clicked, I aim to access and save this particular text. Nonetheless, it seems that once the button is clicked, the content of the DIV resets - lik ...

Laravel's routing system may cause complications when trying to send data via jQuery AJAX post requests

My current challenge involves passing an ID to a PHP script through AJAX. Previously, everything was working perfectly with the code snippet below: var baseURL = '/W4W/public/'; function voteUp(){ var snippetID = document.getElementById(&ap ...

Scope challenges with making multiple rest calls in Angular.js

As a beginner in Angular.js, I am facing an issue with $scope not receiving additional value from one of two $resource rest calls. Below is the code snippet: controller: function ($scope, $modalInstance, $route) { $scope.server = {} ...

Nuxt 3 is throwing an error message stating that the function s.replaceAll is not recognized

I encountered an issue with Nuxt 3 while running it from npm. The error message "s.replaceAll is not a function" keeps popping up, even during the execution of the "nuxt prepare" post-install script. Below is my package.json configuration: { "privat ...

Tips for correctly implementing CORS (Cross-Origin Resource Sharing)

Is there a way to securely access a resource from a third-party domain using XML HTTP Requests (XHR, AJAX)? I have set up CORS on both the target and origin sides with the following configuration: Access-Control-Allow-Origin: http://www.example.com, http ...

Can you help me make a JavaScript Random Number Generator that utilizes HTML input fields and buttons?

I am currently working on developing a random number generator that takes user input through HTML. The idea is to have the user enter two values and then click "submit" to receive a random number within that range. However, I seem to be stuck at this poin ...

How can I display the value entered in a text input field when using ajax upload?

Is there a way to display the value of an input type text when using ajax for file upload? I have successfully implemented code to upload files to a directory called attachments_files, but I am facing an issue. How can I retrieve and echo the value from i ...

end the node.js automated testing process

I'm currently using Jasmine and Zombie JS to create automated tests. I have integrated Drone.io for Continuous Integration, and the tests are executing successfully. However, there seems to be an issue where after passing the tests, the process does n ...

Constructor-generated element doesn't reflect changes upon component re-rendering

Why doesn't the <select> I create in the constructor update correctly when I select a different flavor? The other select and text update, but not this one. class ConstructorComponent extends React.Component { constructor() { super(); ...

Having difficulty deleting an entry from a flatList in a React Native component when using the filter method

I'm currently facing an issue with deleting an item from my flatlist in React Native. I've been attempting to use the filter method to exclude the list item with the ID entered by the user for deletion, but it's not working as expected. I&ap ...