Adding custom type definitions for an untyped npm module in TypeScript 2

Despite attempting various methods recommended in other sources, I am struggling to configure a TypeScript project that utilizes an untyped NPM module. Below is a simplified example along with the steps I have taken.

Let's imagine, for this demonstration, that lodash lacks predefined type definitions. Consequently, we will disregard the @types/lodash package and endeavor to manually introduce its typings file lodash.d.ts into our project.

Directory structure

  • node_modules
    • lodash
  • src
    • foo.ts
  • typings
    • custom
      • lodash.d.ts
    • global
    • index.d.ts
  • package.json
  • tsconfig.json
  • typings.json

Now, let's delve into the files.

File foo.ts

///<reference path="../typings/custom/lodash.d.ts" />
import * as lodash from 'lodash';

console.log('Weeee');

The content of File lodash.d.ts has been directly copied from the original @types/lodash package.

File index.d.ts

/// <reference path="custom/lodash.d.ts" />
/// <reference path="globals/lodash/index.d.ts" />

File package.json

{
  "name": "ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "typings": "./typings/index.d.ts",
  "dependencies": {
    "lodash": "^4.16.4"
  },
  "author": "",
  "license": "ISC"
}

File tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "typeRoots" : ["./typings"],
    "types": ["lodash"]
  },
  "include": [
    "typings/**/*",
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

File typings.json

{
    "name": "TestName",
    "version": false,
    "globalDependencies": {
        "lodash": "file:typings/custom/lodash.d.ts"
    }
}

Despite trying multiple approaches to include typings:

  1. Directly importing it in foo.ts
  2. Using a typings property in package.json
  3. Utilizing typeRoots in tsconfig.json with a file typings/index.d.ts
  4. Employing an explicit types declaration in tsconfig.json
  5. Including the types directory in tsconfig.json
  6. Creating a custom typings.json file and executing typings install

Nevertheless, when compiling Typescript:

E:\temp\ts>tsc
error TS2688: Cannot find type definition file for 'lodash'.

What could be the issue here?

Answer №1

Regrettably, the documentation for these concepts is currently lacking. However, I'll explain your configuration to help you understand how it impacts typescript processing and loading typings.

Let's address the error message you're encountering:

Error TS2688: Cannot find type definition file for 'lodash'.

This error doesn't stem from your imports or usage of lodash in your code, but rather from the incorrect utilization of the typeRoots and types properties. Let's delve deeper into this issue.

The typeRoots:[] and types:[] properties are specific to TypeScript 2.0 feature enabling the packaging and loading of typing declarations from NPM packages.

It's crucial to grasp that these properties exclusively work with folders following the NPM package format (i.e., containing a package.json or index.d.ts).

Default setting for typeRoots is:

{
   "typeRoots" : ["node_modules/@types"]
}

This means TypeScript will search for npm-like packages within the node_modules/@types folder for declaration files.

If the folder structure doesn't match npm conventions, such as in your case, errors like the one you received will occur.

You changed the typeRoot to:

{
    "typeRoots" : ["./typings"]
}

This change tells TypeScript to scan the ./typings folder for subfolders and treat each one as an npm module.

When only using typeRoots to point to ./typings without specifying the types:[] property, errors such as:

Error TS2688: Cannot find type definition file for 'custom'.
Error TS2688: Cannot find type definition file for 'global'.

Will arise because TypeScript interprets the subfolders within ./typings as npm packages due to missing index.d.ts or package.json.

In conclusion, TypeScript 2.0's typeRoots and types cater to automatically loading global declarations packaged in npm modules. For standalone loose .d.ts files or custom typings, traditional inclusion methods must be utilized instead of these new properties.

EDIT:

It's worth noting that typeRoots and types serve primarily for auto-loading global declarations. Any explicit module imports will bypass these settings in favor of other resolution options like baseUrl, paths, and moduleResolution.

To manage type declarations not conforming to npm package structures, consider manual inclusion techniques in your compilation context.

Answer №2

Note: this information may be outdated. Please refer to the previous answer for the most current solution.

Although I'm still a bit confused, I managed to find a fix. You can resolve it by using the provided tsconfig.json:

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "*": [
        "./typings/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

Delete the typings.json file and all content within the typings folder except for lodash.d.ts. Additionally, remove any references starting with ///...

Answer №3

"*": ["./types/*"] I finally resolved everything after a 2-hour struggle thanks to this line in my tsconfig paths.

{
  "compilerOptions": {
    "moduleResolution": "node",
    "strict": true,
    "baseUrl": ".",
    "paths": {
      "*": ["./types/*"]
    },
    "jsx": "react",
    "types": ["node", "jest"]
  },
  "include": [
    "client/**/*",
    "packages/**/*"
  ],
  "exclude": [
    "node_modules/**/*"
  ]
}

types is the name of the folder, positioned next to the node_module at the same level as the client folder (or src folder) types/third-party-lib/index.d.ts
index.d.ts contains

declare module 'third-party-lib';

Note: The configuration above is just a partial example showcasing types, paths, include, and exclude options within it.

Answer №4

While this question may be old, it's important to note that typescript tooling is constantly evolving. One of the most reliable options currently available is to utilize the "include" path settings within tsconfig.json.


  "include": [
        "src/**/*"
    ],

By default, without any specific modifications, all *.ts and *.d.ts files located under src/ will be automatically included. This method proves to be the simplest and most efficient way to incorporate custom type declaration files without having to customize typeRoots or types.

For further information, you can refer to:

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 GraphQl Code Generator fails to correctly generate the graphql() function in Next.js applications

While working on my next.js project, I integrated GraphQL to generate types for queries. However, the code generator is not functioning properly and displaying an error message: "The query argument is unknown! Please regenerate the types." within the gql.t ...

Asynchronous function in TypeScript is restricting the return type to only one promise type

Using node version 14.7.0, npm version 6.14.7, and typescript version 3.7.3. I have a function that interacts with a postgres database and retrieves either the first row it finds or all results based on a parameter. It looks something like this: async fet ...

The value of type 'string' cannot be assigned to type '"menu" | "selectedMenu" | undefined' as it is not compatible with the specified types

I'm working on creating a multiple select feature using TypeScript, material-ui, and React. I am encountering an error when trying to set MenuProps.variant = 'menu'. The error message reads: "Type '{ variant: string; PaperProps: { styl ...

What does it mean when a npm package is intended for use exclusively on the server side?

Is there a way to designate in a package.json that a package is intended solely for server-side use? I encountered a situation where some developers attempted to utilize one of my libraries in the browser, even though it was designed specifically for serv ...

Loading components in an Angular CLI project with the base URL

I recently created an Angular CLI project with various components and transferred it to my school's domain using FileZilla. However, I am looking for a way to automatically redirect the application to the HomeComponent upon loading instead of the AppC ...

Top tips for getting npm bin -g to only display the path

Task I am working on incorporating the path obtained from npm bin -g into a script. Issue When running npm bin -g, it not only returns the path but also displays a message on a new line stating that it is not part of the PATH environment variable: /hom ...

How can you determine when the `prepublish` script is triggered by executing `npm install`?

Click here to learn more about npm scripts prepublish: This script runs before the package is published. It will also run when a local npm install is executed without any arguments. I need my script to only run when the user executes `npm publish`. Unf ...

Encountering issues when verifying the ID of Angular route parameters due to potential null or undefined strings

Imagine going to a component at the URL localhost:4200/myComponent/id. The ID, no matter what it is, will show up as a string in the component view. The following code snippet retrieves the ID parameter from the previous component ([routerLink]="['/m ...

Challenges with date formatting arise for Spanish speakers when the date returns as NaN or an Invalid

I have been working on an Angular app Objective: My aim is to allow users to input dates in Spanish format (DD/MM/YYYY) and display them as such, while converting them back to English format when saving the data to the Database. Issue: One problem I enco ...

Angular V8 build is not functioning correctly because it is broken

Unexpectedly, our ng build task in the VSTS pipeline is no longer functioning. Initially, the issue only appeared on VSTS, but when I cleared and reinstalled the node_modules on my local machine, I was able to replicate the problem. This leads me to believ ...

Intro.js is not compatible with React and Remix.run

I am currently working on implementing onboarding modals for header links using intro.js within a React environment. Below is the code snippet: import { useState, type FC } from 'react' import type { Links } from '../types' import &apo ...

A single npm package designed for diverse assembly languages

My project is built using node.js. Development occurs on two separate machines: one with x32 architecture and the other with x64 architecture. The issue arises when certain npm modules conflict due to different environments. One example is dNode. I instal ...

Issue encountered in WebStorm: Unable to start Karma server due to a TypeError stating that undefined is not a function when trying to execute

Recently, I updated my WebStorm to the latest version (10.0.4). Today, I decided to integrate karma into my project. To do so, I installed Python and ran these commands: npm install -g karma npm install karma npm install karma-jasmine npm install karma-ch ...

Is it possible for a factory provider to include optional dependencies?

As an illustration: @NgModule ({ providers: [ { provide: MyService, useFactory: (optionalDependency) => new MyService(optionalDependency) deps: [ANOTHER_DEP] } }) class MyModule {} Is it possible for useFactory to include optio ...

Setting up ESLint and Prettier with TypeScript on Node 20: A Guide

I attempted to set up Prettier with ESLint and crafted a configuration in settings.json to rectify errors upon saving, but the errors only manifest in .js files and not .ts files. How can I adjust this? Dependencies: "@eslint/js": "^9.4.0& ...

Specify the location of `~/.config` in Bower

I am encountering an issue with a user who lacks the necessary permissions to create directories in their home directory. While attempting to use bower install, I am receiving errors. Is there a way for me to specify the location of the .config directory ...

Utilizing getServerSideProps in the new app router (app/blah/page.tsx) for maximum functionality

I am a beginner in Next.js and I am currently experimenting with the new app router feature by placing my pages under app/.../page.tsx The code snippet provided works when using the page router (pages/blah.tsx) but encounters issues when used in app/blah/ ...

What is the process for updating the registry in the package-lock.json file?

The current package registry specified in the package-lock.json file is set to http://registry.npm.taobao.org/. package-lock.json: { "name": "webpack", "version": "1.0.0", "lockfileVersion": 1, &qu ...

Merge is showing an error message indicating that I am trying to import runtime.js from outside the src directory, even though the file structure remains unchanged

I've noticed that most questions about a similar issue involve users intentionally trying to import files from outside their project. However, I recently performed a merge between branches that did not alter my folder structure, yet I'm encounter ...

Encountering issues with npm installation due to the errno -2 error

I encountered errors while attempting to install npm, as indicated below: npm ERR! install Couldn't read dependencies npm ERR! Darwin 14.5.0 npm ERR! argv "/Users/bunniehsieh/.nvm/versions/node/v4.1.0/bin/node" "/Users/bunniehsieh/.nvm/ ...