package.json 导出中的键顺序

问题描述 投票:0回答:3

我相信我了解

exports
文件中
package.json
键的基本功能:

// package.json
{
  "exports": {
    ".": {
      // used by typescript
      "types": "./file_with_type_defs.d.ts",
      // used by ESM resolution
      "import": "./file_to_import.mjs",
      // used by CJS resolution
      "require": "./file_to_require.cjs",
      // used by ...others?
      "default": "./file_one_more.js"
    }
  }
}

问题: “types”、“import”、“require”和“default”键的顺序重要吗?通常我认为不可能,因为 JSON 对象键是无序的。来自json.org

对象是一组无序的名称/值对。对象以 { ...

开头

但是 Typescript 文档 说“类型”必须放在第一位:

TypeScript 解析的入口点 - 必须首先出现!

“类型”:“./types/index.d.ts”

并且 NodeJS 文档 说“默认”应该放在最后

“default” - 始终匹配的通用后备。可以是 CommonJS 或 ES 模块文件。这种情况应该总是最后出现的。

那么...导出键的顺序重要吗?如果不是,NodeJS 和 Typescript 文档中提到的“第一个”和“最后一个”是什么意思?

将“类型”的顺序与其他键交换后,其顺序似乎并不重要

node.js json typescript es6-modules
3个回答
4
投票

Webpack,也使用

export
解释此字段如下:

订购须知

在每个键都是一个条件的对象中,属性的顺序很重要。条件按照指定的顺序进行处理。

与其将其视为普通对象,不如将其视为 if-else 情况:

let file;
if (platform_supports('types')) {
      file = "./file_with_type_defs.d.ts";
} else if (platform_supports('import')) {
      file = "./file_to_import.mjs";
} else if (platform_supports('require')) {
      file = "./file_to_require.cjs";
} else if (true) { // default
      file = "./file_one_more.js";
}

如果你要调换顺序,可能会是这样的:

let file;
if (true) { // default
      file = "./file_one_more.js";
} else if (platform_supports('types')) {
      file = "./file_with_type_defs.d.ts";
} else if (platform_supports('import')) {
      file = "./file_to_import.mjs";
} else if (platform_supports('require')) {
      file = "./file_to_require.cjs";
}

即使 Typescript 能够理解

.d.ts
文件,它也会使用
file_one_more.js
,因为它首先匹配。

我尝试过用其他键交换“类型”的顺序。好像没什么关系。

Typescript types 条件可能会优先于其他条件。然而,我会坚持他们的建议——毕竟“必须首先发生”并不是“应该首先发生”。


顺便说一句,历史上 JavaScript 对象键是无序的/不保证顺序。实际上,浏览器确实保留了键顺序,并且这种行为在 ES2015 中得到了标准化:非整数键按插入顺序保留。

JSON 标准没有做出相同的承诺,因为 JSON 解码器有许多不同语言的实现,并且它早于 ES2015 标准。


1
投票

解析的 JS 对象确实具有与 JSON 中的组织匹配的键顺序

根据代码是否使用

for (let k in json)

if (json.types)
,行为可能会有所不同
因此,无论出于何种原因,建议按照某些解析器可能期望的方式对键进行排序

就您而言,我建议您尝试交换它们,看看没有任何反应,然后再将它们交换回来


0
投票
arethetypeswrong

的好工具遇到了这个问题。 来自他们的

文档

🐛 使用后备条件

导入通过条件 package.json 导出解析为类型,但仅在无法通过早期条件解析之后。此行为是一个

TypeScript bug

。它可能会歪曲此导入的运行时行为,因此不应依赖它。

因此,
"types"

导出在没有首先出现的情况下工作是一个错误,不应该依赖,尽管似乎有动机保留当前的行为。

当你写这个问题时,我和你一样困惑,因为我还假设 JSON 键没有排序(所以这应该不重要,但正如所说的,确实如此)。

感谢

RickN 的回答

,我们知道 JS 实现在这种情况下确实保留了顺序。 我留下这个答案只是为了指出 TypeScript 的

issue

,以便让未来的读者清楚“它正在工作”正式是一个错误,而不是一个功能。

© www.soinside.com 2019 - 2024. All rights reserved.