'How does VS Code determine the return values of `require()`?

I found that some kinds of type declarations in JavaScript can't be analyzed correctly in VS Code.

Examples:

For example, when I tried to require a package express-promise-router like:

const router = require('express-promise-router')();

This package has an index.d.ts with the content below:

declare module 'express-promise-router' {
  import { Router, RouterOptions } from 'express';

  function PromiseRouter(options?: RouterOptions): Router;

  export default PromiseRouter;
}

But VS Code thought this statement would return any type and broke the related type annotations.

By the way, ES6 imports like import Router from 'express-promise-router' or only changing the export default PromiseRouter to export = PromiseRouter can solve the problem.

Another example is my own package. A JavaScript lib named database.js has its declaration file named database.d.ts. The content is like:

// database.d.ts
// ...
export type ActiveClientsConn = MySQLConn & ActiveClientsSpecMethods;
// database.js
// ...
/**
 * @param {import('./database').ActiveClientsConfig} params
 */
function ActiveClientsConn(params={}) {
  /** @type {import('./database').ActiveClientsConn} */
  let inst = MySQLConn(params);
  // ...
  return inst;
}
// ...

VS Code can correctly handle the return value of ActiveClientsConn() in database.js. But when it comes to another script (like database_test.js) and I try to require it:

const database = require('./database');
const conn = database.ActiveClientsConn(params);

VS Code still can't give the expected type hint for conn (any given, database.ActiveClientsConn expected).

Other information:

  • VS Code version: 1.66.0
  • Node.js: 16.13.0
  • package.json:
{
  "name": <omitted>,
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "bencode-js": "^0.0.8",
    "chalk": "^4.1.2",
    "cookie-parser": "~1.4.4",
    "express": "~4.16.1",
    "express-promise-router": "^4.1.1",
    "lodash": "^4.17.21",
    "morgan": "~1.9.1",
    "mysql": "^2.18.1",
    "promise-mysql": "^5.1.0",
    "redis": "^4.0.4",
    "yaml": "^1.10.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.13",
    "@types/mysql": "^2.15.21",
    "@types/node": "^17.0.18",
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@typescript-eslint/parser": "^5.12.0",
    "eslint": "^8.9.0"
  }
}

So is there anything wrong with the type-hinting system of VS Code or the code? Any reply is appreciated.


UPDATE:

tsconfig.json:

{
    "compilerOptions": {
        "target": "es2021",
        "module": "commonjs",
        "sourceMap": true,
        "declaration": true,
        "rootDir": ".",
        "allowJs": true,
        "allowSyntheticDefaultImports": true,
        "isolatedModules": true,
        "noEmit": true,
        "maxNodeModuleJsDepth": 2
    },
    "include": [
        "**/*.d.ts"
    ]
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source