ChatGPT解决这个技术问题 Extra ChatGPT

我如何决定 @types/* 是否进入 `dependencies` 或 `devDependencies`?

我在我的项目中使用 TypeScript 2。我想使用一些 js 库,但也想使用该库的类型。我可以使用简单的 npm install @types/some-library 安装类型。我不确定我应该--save 还是--save-dev 他们。在我看来,即使是 DefinetelyTyped GitHub 自述文件,也提到了这两个版本,但从未解释过它们。我认为@types 应该在 devDependencies 中,因为类型是开发所需要的并且不在运行时使用,但我在 dependencies 中多次看到 @types。我很困惑。

我应该如何决定是 @types/* 进入 dependencies 还是 devDependencies?实际上是否有一些或多或少的官方说明?

您是在生成一个捆绑包还是这是一个将被其他人使用的包?如我所见,在后一种情况下,您只需要区分 dependenciesdevDependencies
我从头开始用 js/ts 制作一些游戏。我将所有东西都与 webpack 捆绑在一起。 atm 根本没有后端,但有可能我会将它全部包装在 Electron 中以使其有一天独立。我认为没有人会在他们自己的应用程序中使用它作为依赖项,但我想这是可能的(想想 GTA 游戏中的迷你游戏;我的游戏是开源的)。尽管如此,我还是想学习并遵循最佳实践,这也是我制作这款游戏的主要原因。我希望我能很好地阐明我的用例。 :)
是的,这是有道理的,只是想确保我的原始答案与您的用例相关。我仍然认为 devDependenciesdependencies 之间的区别在构建捆绑包时无关紧要,它是 create-react-app 强制执行 as well 但最终由您选择

A
Anton Rudeshko

假设您正在开发一个包“A”,它在 devDependencies 中有 @types/some-module 包。由于某种原因,您要从 @types/some-module 导出类型:

import { SomeType } from 'some-module';

export default class APackageClass {
  constructor(private config: SomeType) {
    // …       
  }
}

现在,包“A”的 TypeScript 使用者无法猜测 SomeType 是什么,因为包“A”的 devDependencies安装。

在这种特殊情况下,您需要@types/* 包与常规 dependencies 一起放置。对于其他情况,devDependencies 就足够了。


所以你的意思是,如果我只在实现中使用类型,它的类型定义可以是devDependencies
是的@FranklinYu。一旦该类型出现在声明文件中,您就需要将其放在 dependencies 上。否则 devDependencies 很好
但是一个包适用于 TS 和 JS。 JS 开发人员不需要这些类型来编译他们的代码。将类型定义添加到 dependencies 会使依赖关系树变得臃肿。
@TylerLong 正确。这并不完美,但这就是现实。可选地,您也可以使用“optionalDependencies”,但我相信在规模上它可能会很烦人。
我想如果我正在开发一个最终用户应用程序而不是一个包,我可以将所有 @types/.. 移动到 devDependencies 中,对吗?
V
Valentin

如果您只是生成一个包,则可能不需要区分 dependenciesdevDependenciesnpm 的此功能通常在发布可供其他人使用的包时很有用,并且您不想向他们发送带有冗余依赖项的垃圾邮件。

在其他用例中,拆分依赖项可能会有所帮助,但除非您对此有明确需求,否则我的建议是选择其中一个并将所有内容放在那里。如果需要的话,事后拆分它们并不难。

这种做法 IRL 的一个著名示例是 create-react-app,默认情况下,它创建的未弹出样板将所有内容放在 dependencies 中,请参阅 this threadthis answer


如果您不发布包,那是正确的,但如果您发布了,它与开发与运行时无关,也与构建此包所需的一切与使用此包所需的一切无关。
@Yogu这就是我首先做出区分的原因所以是的,我完全同意你的看法
我不同意这个建议。执行 npm install --production(或 npm ci --production)时未安装 devDependencies,因此在运行生产代码时不可用。这对于服务来说是一个非常有意义的区别,而不仅仅是图书馆。
@BradWilson您说得有道理,阳光下有很多npm工作流程,如果您的用例要求您做出区分,那么请务必这样做。随意为这个困境提供你自己的答案。
我已经更新了我的答案,提到了其他用例的存在,这些用例的区别可能是有意义的,并给出了现实世界的例子。感谢您的反馈!
C
Carsten Führmann

在将 Node.js 应用程序部署到生产环境的特殊情况下,人们只想安装运行应用程序所需的依赖项。

npm install --production

npm ci --production

yarn --production

在这种情况下,类型应该在 devDependencies 中,以防止它们使安装膨胀。

(为避免误解,在构建应用程序的机器上不得使用 --production 选项,否则 TypeScript 编译器会报错。)

备注:我知道布拉德威尔逊在另一个答案的评论中提到了这一点。不过,这一点似乎值得回答。


我正在使用 3rd 方库开发应用程序,将所有 @types/* 包放在 devDependencies 中,但随后生产构建失败,因为 typescript 在生产构建中寻找这些类型。
@omerts:当您写“在生产构建中查找这些类型”时,您的意思是“在编译期间在 package.json 中查找这些类型”吗?我问是因为生产构建是在目标机器上运行的,如果在那个阶段调用 TypeScript 编译器会很奇怪。另一方面,如果您谈论的是在 developer 机器上进行编译,那么 devDependencies 在那个阶段应该仍然存在,因为 --production 应该只在为生产安装时使用 - 而不是在开发人员上机器。
在打开生产标志的情况下运行 yarn/npm install,然后在 CI 或 docker env 中进行 yarn build 时,typescript 编译器将由于缺少类型而失败。
问题似乎是您已经在构建应用程序的机器上使用了 --production 选项。相反,该选项应仅在运行应用程序的机器上使用,而不是在构建的机器上使用。我在这方面澄清了我的主要答案。
@omerts 虽然有时可以将节点模块从构建机器复制到主机(即运行应用程序的机器),但这似乎是一个有问题的做法,因为:即使主机上的 Node.js 版本号相同与构建机器不同,目标机器可能是不同的操作系统。例如,您可能在 Windows 上开发,但在 Linux 上运行。在某些情况下,例如 Windows 上的 npm install 的输出在 Linux 上是不正确的。
Z
Zim

其他答案很有意义,但我要补充一点,peerDep 的类型声明包也应该放在 dependencies 而不是 peerDependencies 中。

假设 ba 的插件。 c 使用 ab

为什么不应该将 @types/a 放在 bpeerDependencies 中?

如果 bpackage.json 类似于:

{
  "peerDependencies": {
    "a": "1.5.x"
    "@types/a": "1.4.x"
  }
}

c 只能使用 @types/a@1.2.x 中定义的接口,但 c 必须安装 @types/a@1.4.x

此外,c 可能是常规 javascript 包而不是 typescript 包,但 c 也必须安装 @types/a@1.4.x

因此,b 的正确 package.json 应该是:

{
  "peerDependencies": {
    "a": "1.5.2"
  },
  "dependencies": {
    "@types/a": "1.4.x"
  }
}