如何使用正确的 "module" 为遗留 CommonJS 依赖项发出 TS 声明

How to emit TS declarations for legacy CommonJS dependencies with correct "module"

我正在尝试为我使用的旧依赖项生成类型声明,它们发出 CJS 模块并且没有自己的类型。例如,aabb-3d 模块(尽管此问题并非特定于该模块)。

我正在使用如下命令生成声明:

tsc node_modules/aabb-3d/index.js 
    --allowJs 
    --declaration 
    --emitDeclarationOnly 
    --outFile types/aabb-3d/index.d.ts

这行得通,并且生成了声明,但文件的内容如下所示:

declare module "index" {
    export = AABB;
    function AABB(pos: any, vec: any): AABB;
    //...

当我随后尝试编辑代码时,我的编辑器没有选择类型,因为它希望声明是声明模块 aabb-3d,而不是 index

如果我手动更改生成的 d.ts 文件,我的编辑器可以正常工作,并且代码提示对于遗留模块也可以正常工作。如何让 tsc 生成工作声明文件?

我检查了 TypeScript 自己的代码,没有明显的方法可以更改 declare module 行的生成方式。幸运的是,您完全可以阻止它生成。您正在获取环境外部模块声明 (declare module),因为您使用的是 --outFile 而不是 --outDir。下面是如何在没有 declare module:

的情况下生成与 ES 样式模块声明相同的 types/aabb-3d/index.ts 文件
tsc node_modules/aabb-3d/index.js 
    --allowJs 
    --declaration 
    --emitDeclarationOnly 
    --outDir types/aabb-3d

为了让 TypeScript 在 types 树中找到 ES 风格的模块声明,您需要在项目的 tsconfig.json 中添加以下内容:

{
    ...
    "compilerOptions": {
        ...
        "typeRoots": [
            "./types",
            "./node_modules/@types"
        ],
        "baseUrl": "./",
        "paths": {
            "*": [
                "./types/*",
                "*"
            ]
        }
        ...
    }
    ...
}

然后您可以 import aabb3d from 'aabb-3d' 在您的代码中输入适当的内容,例如当 tsc 自动生成它时。

如果包的 "main" 文件未命名为 index.js,因此生成的声明也未命名为 index.d.ts,您需要将 package.json 文件放入types/$package 目录将编译器指向正确的文件。例如,如果主文件是 main.js,声明文件是 main.d.ts,那么 package.json 将是:

{
    "types": "main.d.ts"
}