新的 package.json `exports` 字段不适用于 TypeScript

Luc*_*ems 22 node.js typescript

Node.js 13.2 版允许 ESM 模块和一个package.json名为的新字段exports来选择和重写导出的文件。

在 13.2 之前,我从dist我的库文件夹中导入文件:

import myfile from 'mylibrary/dist/myfile'
Run Code Online (Sandbox Code Playgroud)

在 13.2 中,我将此添加到我的package.json

exports: {
    "./": "./dist/"
}
Run Code Online (Sandbox Code Playgroud)

并尝试导入文件:

import myfile from 'mylibrary/myfile'
Run Code Online (Sandbox Code Playgroud)

但是 Typescript 引发了 2307 错误,说未找到该模块。

Igo*_*rev 66

它终于在Typescript 4.7中可用

您的图书馆:

// package.json
"exports": {
  ".": "./dist/index.js",
  "./svg": "./dist/svg.js",
  "./html": "./dist/html.js",
  "./package.json": "./package.json"
},
Run Code Online (Sandbox Code Playgroud)

您的客户端代码必须具有:

// tsconfig.json
"compilerOptions": {
  "moduleResolution": "node16" // or "nodenext"
}
Run Code Online (Sandbox Code Playgroud)

在 Typescript 4.7 之前,您可以使用typesVersions

// package.json
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
  ".": "./dist/index.js",
  "./svg": "./dist/svg.js",
  "./html": "./dist/html.js",
  "./package.json": "./package.json"
},
"typesVersions": {
  "*": {
    "svg": ["dist/svg.d.ts"],
    "html": ["dist/html.d.ts"]
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 看来你需要在 tsconfig.json 中设置 `moduleResolution`=`Node16`/`NodeNext` 才能使其工作 (19认同)
  • 不幸的是,它[没有登陆 4.5](https://github.com/microsoft/TypeScript/issues/33079#issuecomment-1026476142)。它终于[登陆 4.7](https://github.com/microsoft/TypeScript/issues/33079)。 (14认同)
  • 我正在使用 TS 4.5.2,但它仍然无法工作 (9认同)
  • @ThisCompSciGuy 我无法让这个与 glob 一起工作。你知道是吗? (4认同)
  • Typescript 4.7,但对我来说仍然不起作用:-( (4认同)
  • 另请注意,此 moduleResolution 需要在使用项目中设置,而不是在库的 (2认同)

小智 11

对于那些在经历了看似无尽的挫折和困惑之后在这里跌跌撞撞的人:

\n
\n

重要: \n当\n设置为或 时才
支持节点包导入moduleResolution"nodenext""node16"

\n
\n
    \n
  • tsconfig.json
  • \n
\n
{\n  "compilerOptions": {\n    //                  \xe2\x88\xa8\n    "moduleResolution": "nodenext"\n    // <... config>\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果设置好了,它将顺利工作。项目中的示例:

\n
    \n
  • package.json
  • \n
\n
{\n  "type": "module",\n  "imports": {\n    "#util.define": "./src/util/define.ts"\n    // <... etc.>\n  }\n  // <... config>\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • main.ts
  • \n
\n
{\n  "compilerOptions": {\n    //                  \xe2\x88\xa8\n    "moduleResolution": "nodenext"\n    // <... config>\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n


Iva*_*asa 6

TypeScript 方面需要做一些工作来支持这一点。该功能在 github 中进行了跟踪。在该链接中还列出了一些解决方法。


Mac*_*zyk 6

TypeScript 4.7+ 完整解决方案

当前的最佳答案对我来说还不够 - 当尝试在包含 module:bundler 的包中使用该库时,我会收到以下错误。

错误 TS7016:找不到隐式具有“any”类型的模块 X 的声明文件。X 处有类型,但在考虑 package.json“导出”时无法解析此结果。X 库可能需要更新其 package.json 或类型。

package.json 中的完整定义需要在导出中进行类型声明。此外,如果您同时提供 ESM 和 CommonJS,则需要使用不同的类型定义文件(出于某些未知原因) - 我通过使用 rollup-plugin-copy 解决了这个问题

包.json

  ...
  "main": "./dist/index.common.js",
  "module": "./dist/index.mjs",
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.mts",
        "default": "./dist/index.mjs"
      },
      "require": {
        "types": "./dist/index.d.ts",
        "default": "./dist/index.common.js"
      }
    }
  },
  "types": "./dist/index.d.ts",
  ...

Run Code Online (Sandbox Code Playgroud)

typesmodule是可选的,用于遗留支持。main如果定义了导出,那么它也可能是可选的,如果 package.jsontype没有定义为“模块”,那么它应该是 Common.js,否则 ESM 另请注意,最好对模块使用 .mjs 扩展名,CommonJS 也有 cjs 扩展名(和 .d.cts)但常规 .js 很好并且向后兼容。

请注意,“类型”条件应始终位于“导出”中的第一位。[0]

如果使用 Rollup,则可以使用 rollup-plugin-copy 来复制声明文件:

rollup.config.mjs

import copy from 'rollup-plugin-copy';

export default [
  // ...
  {
    // ...
    plugins: [
      // ...     
      copy({
        targets: [
          { src: 'dist/index.d.ts', dest: 'dist', rename: 'index.d.mts' },
        ],
      }),
    ]
  }
];
Run Code Online (Sandbox Code Playgroud)

此外,该实用程序可以帮助确保您正确获取此信息。

[0] https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/