Creating Typescript declarations for local JavaScript files

As part of our transition to Typescript at work, I've been working on adding typings to our Javascript files. However, I'm facing an issue with getting the declaration files recognized.

Below is my file structure:

  • js
    • Foo.js
  • typings
    • Foo
      • index.d.ts
  • index.ts
  • package.json
  • tsconfig.json

Foo.js

module.exports = function Foo() {
   return 'Bar';
 };

index.d.ts

export = Foo;

declare function Foo(): string;

index.ts

import Foo = require('./js/Foo')

console.log(Foo());

tsconfig.json

{
  "compilerOptions": {
    "typeRoots": ["./typings"],
    "target": "es5",
    "strict": true,
    "baseUrl": "./",
    "paths": {
      "*": ["typings/*"]
    }
  }
}

package.json

{
  "name": "fail",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "scripts": {
    "tsc": "tsc"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "typescript": "^3.1.4"
  }
}

To see the problem in action, check out the repository here.

Edit: Below is the error message I receive:

error TS7016: Could not find a declaration file for module './js/Foo.js'. '....../js/Foo.js' implicitly has an 'any' type.

Answer №1

If you're looking to provide declarations for a relative import like './js/Foo', there are a couple of approaches you can take. One option is to have the declaration file located at the import path, with either a .d.ts or /index.d.ts extension. Another option is to virtually place the declaration file at the import path using the rootDirs option. In this scenario, typeRoots and baseUrl/paths do not have any impact: baseUrl/paths only influences module resolution for "non-relative" paths, while typeRoots helps TypeScript load files but does not alter the connection between import paths and files.

A straightforward solution would be to include a Foo.d.ts file in the same directory as Foo.js. If you prefer to keep the typings in a separate folder, you can modify your tsconfig.json by adding "rootDirs": ["js", "typings"]. This adjustment should enable the example to function properly. However, having both Foo.js and Foo/index.d.ts files might lead to confusion. It's advisable to maintain consistency in your subdirectories, such as switching to Foo/index.js on the JavaScript side or opting for Foo.d.ts on the TypeScript side.

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

Attempting to include an additional choice in a dropdown menu

I have been facing an issue with the code snippet below where it removes all the options in my edit form. However, after removing the options, I am trying to add a default option. Despite my attempts with the given code along with .add and .prepend meth ...

Guidelines for removing a 2D Primitive in processing

I am facing issues with deleting 2D primitives. I attempted to create a rectangle in front of these primitives to conceal them. However, I need to hide them when clicking somewhere, which leads me to believe that the draw() function is overriding the mouse ...

The 'wrapper' property is not present in the 'ClassNameMap<never>' type in Typescript

Hey there, I've been encountering a puzzling issue in my .tsx file where it's claiming that the wrapper doesn't exist. My project involves Material UI and Typescript, and I'm relatively new to working with Typescript as well as transiti ...

Even when only a handful of modules are utilized, Webpack still imports a significantly large existing chunk

Currently, I am working on enhancing the splitChunks configuration in a multi-page application that utilizes Webpack 5, with a PHP backend and a Vue frontend. To optimize the vendor file size, I have started customizing the test function of the vendor cac ...

Switching Languages in react-simple-keyboard: Explained

import React, { useRef, useState } from "react"; import Keyboard from "react-simple-keyboard"; import "react-simple-keyboard/build/css/index.css"; function App() { const [input, setInput] = useState(""); const [ ...

Crafting callback functions

My jQuery code looks like this: $('#current_image').fadeOut(function(){ $('#current_image').attr('src',newImage).show(); }); This process is wonderful - the nested function runs smoothly after the fadeOut. I ...

How can I add a comma to a number input field when the numbers reach one thousand?

When setting the minimum and maximum prices of products, I encountered an issue where entering 10.000 displayed as 10000. To automatically add a decimal point to numbers and display it correctly as 10.000, I attempted the following solutions: <input typ ...

AngularJS: default radio button selection

I'm currently working on creating a color configurator using AngularJS with radio buttons. Everything seems to be functioning properly - the data binds correctly, etc., but I'm encountering an issue setting the default color radio button as check ...

When incorporating a Textarea element within styled components in ReactJS, it causes the text to be inputted backwards due to the cursor

Currently, I am utilizing the Textarea component from react-textarea-autosize along with using styled from styled components. In a class, I have created a function called renderForm which is responsible for rendering a form containing a StyledTextarea. How ...

What is the relationship between Angular's $watch function and a slider component?

Hello everyone! I am a beginner in the world of Web Development and I've run into an issue. Luckily, I was able to create a fiddle showcasing my problem for better understanding. The challenge at hand involves two sliders: one for a value and another ...

What steps are required when utilizing ngModelOptions allowInvalid = true in AngularJS?

As a newcomer to AngularJS, I am currently navigating a complex form and it seems like incorporating the ngModelOptions { allowInvalid: true } option could prove beneficial. I can only assume that AngularJS's default behavior of discarding the model ...

Guide on integrating the highcharts-border-radius plugin into a LitElement web component

Developed a custom web component with LitElement and incorporated a columnrange chart using highcharts. I wanted to apply border radius exclusively to the top left and top right corners of the bars. To achieve this, I attempted to use the highcharts-border ...

AngularJS allows you to create nested tables and dynamically show or hide them using the

When I click on a row in my table, I want to display a new child table right below the clicked row. I am fetching new data from an API on row click, and I need to display it in a new table immediately after the clicked row. You can see how it should look i ...

Callback function located within directive attribute specified in separate attribute

Recently, I created a directive called mySave, and it looks like this: app.directive('mySave', function($http) { return function(scope, element, attrs) { element.bind("click", function() { $http.post('/save', scope.d ...

Prevent a module from initializing upon importing in JavaScript

I'm currently developing a notification system and facing challenges on how to instantiate a function dynamically rather than just when it is imported. For instance: Here is the structure of my notification function: const sendNotification = async ( ...

Having trouble selecting checkboxes in React Native

When working on React Native tests, I utilize react-native-paper. Below is the code snippet: {(!props.question.isSingleAnswer && props.question.answers.length) && <View> {props.question.answers.map((item) => ( ...

IE11/Edge exhibits slow performance with components that have large datasets exclusively

Take a moment to analyze the following code snippet: <GridBody Rows={rows} />. Let's say that in this scenario, rows.length could reach 2000 or more, with each array containing approximately 8 columns. I have encountered a performance bottleneck ...

Change the output of the console.log() function in Node.js to show text instead of displaying <Buffer>

Despite my best efforts, I'm encountering a peculiar issue where node is displaying my console.log() text as a Buffer. This problem only occurs in the VSC powershell integrated terminal; the message displays correctly in the browser. client.html < ...

A fresh perspective on incorporating setInterval with external scripts in Angular 7

Incorporating the header and footer of my application from external JavaScript files is essential. The next step involves converting it to HTML format and appending it to the head of an HTML file. private executeScript() { const dynamicScripts = [this.app ...

What is the most effective way to display a card with varying values depending on the user's input in a form?

For a while now, I've been grappling with a particular challenge. In my project, I am utilizing multiple states to display values within a card after they are entered into a form. The first state captures the values and modifies the initial state, whi ...