通过 npm 包共享 TypeScript 类型声明

Leo*_*ada 10 types npm type-declaration typescript es6-modules

我需要在我的 React 客户端和 Express REST API 之间共享一些 TypeScript 类型,以保持代码干净和干燥。\n由于这是一个私有项目,我不会通过 @types 存储库共享这些类型,所以我按照 TypeScript 网站上的指南进行操作,这就是结果......

\n

React 客户端中的一切都运行良好:我已将类型安装为开发依赖项并完美地使用它们。

\n

在 Express API 中,我收到此错误,我认为它与我构建包的方式有关。

\n

我做错了什么?\n尽管我很无知,但我认为这与模块的加载方式有关,但我无法准确地弄清楚是什么导致了错误。

\n
> cross-env NODE_ENV=production node dist/index.js\n\ninternal/modules/cjs/loader.js:834\n  throw err;\n  ^\n\nError: Cannot find module \'@revodigital/suiteods-types\'\n
Run Code Online (Sandbox Code Playgroud)\n

如何在 API 代码中导入模块

\n
> cross-env NODE_ENV=production node dist/index.js\n\ninternal/modules/cjs/loader.js:834\n  throw err;\n  ^\n\nError: Cannot find module \'@revodigital/suiteods-types\'\n
Run Code Online (Sandbox Code Playgroud)\n
\n包树\n
suiteods-types\n  |_index.d.ts\n  |_package.json\n  |_README.md\n  |_tsconfig.json\n\n
Run Code Online (Sandbox Code Playgroud)\n

索引.d.ts

\n
import { AuthEntity, Roles } from \'@revodigital/suiteods-types\';\n\n@Model()\nexport class AuthEntityModel implements AuthEntity {\n  /* ... */\n\n  role: Roles;\n\n  /* ... */\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

包.json

\n
suiteods-types\n  |_index.d.ts\n  |_package.json\n  |_README.md\n  |_tsconfig.json\n\n
Run Code Online (Sandbox Code Playgroud)\n

tsconfig.json

\n
export = Ods;\nexport as namespace Ods;\n\ndeclare namespace Ods {\n  /* ... */\n  interface AuthEntity extends DomainObject {\n    email: string;\n    password: string;\n    role: Roles;\n    instanceId: string;\n  }\n\n  enum Roles {\n    BASE,\n    STUDENT,\n    BUSINESS,\n    INSTRUCTOR,\n    ADMIN\n  }\n  /* ... */\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

更新

\n对如何摆脱名称空间感到困惑,并且在模块上仍然遇到相同的错误,现在安装为“dependency”而不是“devDependency”。\n文件结构与上面相同。\n提前感谢您帮助。\n

更新并完成index.d.ts

\n
{\n  "name": "@revodigital/suiteods-types",\n  "version": "0.1.1",\n  "description": "Type declarations for suiteods project",\n  "types": "index.d.ts",\n  "scripts": {\n    "test": "echo \\"Error: no test specified\\" && exit 1"\n  },\n  "author": "Revo Digital",\n  "license": "ISC",\n  "repository": {\n    "type": "git",\n    "url": "git+https://github.com/revodigital/suiteods-types.git"\n  },\n  "bugs": {\n    "url": "https://github.com/revodigital/suiteods-types/issues"\n  },\n  "homepage": "https://github.com/revodigital/suiteods-types#readme"\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Leo*_*ada 10

除了宝贵的 @Paleo 编辑之外,添加包含以下内容的 index.js 文件也解决了该问题。


索引.js

module.exports = {};
Run Code Online (Sandbox Code Playgroud)

更新的文件结构

suiteods-types
  |_index.d.ts
  |_index.js
  |_package.json
  |_README.md
  |_tsconfig.json

Run Code Online (Sandbox Code Playgroud)

请参阅GitHub 存储库以获取完整代码。


那么...如何通过 npm 共享 TS 类型

如果您想共享一些 TypeScript 类型(例如在客户端和服务器之间,就像我的情况一样),则遵循以下步骤(对我有用)。
  1. 创建一个新文件夹并将其初始化为 npm 包npm init
  2. 推断您想要在实体之间共享的所有类型并将它们分组到一个index.d.ts文件中
  3. 仅声明“纯类型”,在我的例子中,将枚举转换为类型(并进行一些重构以适应代码的其余部分)就足够了
  4. 添加tsconfig.json(请参阅我上面的问题作为示例)
  5. 添加index.js仅包含module.exports = {}
  6. 发布它(见下面的链接)
  7. 将其安装为dependency,所以 `npm i --save @yourscope/yourpkg
  8. 需要的时候消耗它

为了发布包,我使用了 npm 和 GitHub 包。请参阅这些链接...


Pal*_*leo 5

问题

\n

类型enum不是纯类型。TypeScript 编译器会为此类型生成一些 JavaScript 代码。您的其余代码需要它。

\n

在运行时,正常部署后,您的代码无法访问“开发依赖项”。仅安装了依赖项。

\n

就您的前端而言,Webpack 有一点魔力。在构建时,Webpack 会遵循所有依赖项(包括开发依赖项)中的代码,并将它们打包。因此,您的私有依赖项的编译代码位于捆绑包中并且可以正常工作。

\n

解决方案

\n

解决方案 1:可以@revodigital/suiteods-types仅使用运行时使用的 javascript 代码来发布包。然后该包可以用作常规依赖项。

\n

解决方案2:可以在后端使用捆绑器(Webpack或Rollup)来打包所使用的代码。私有包的打包方式与前端相同。

\n

解决方案 3:将私有包中的类型设为“纯类型”,这样在运行时根本不需要它。enum用字符串并集替换所有类型。

\n

例如:

\n
enum Roles {\n    BASE,\n    STUDENT,\n    BUSINESS,\n    INSTRUCTOR,\n    ADMIN\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\xa6 可以替换为:

\n
type Role = "BASE" | "STUDENT" | "BUSINESS" | "INSTRUCTOR" | "ADMIN"\n
Run Code Online (Sandbox Code Playgroud)\n

注意:这需要一些重构。

\n

额外的免费建议:不要保留名称空间

\n

不建议namespace在模块中使用 a。你应该摆脱它。

\n

当前代码:

\n
export = Ods;\nexport as namespace Ods;\n\ndeclare namespace Ods {\n\n  type IdType = 'Carta Identit\xc3\xa0' | 'Passaporto' | 'Patente'\n  \n  type ODSModule = 'SCUOLA' | 'OPERATORI' | 'DRONI' | 'ODS_ROOT'\n\n  // ...\n\n  interface Address {\n    street: string;\n    city: string;\n    province: string;\n    CAP: string;\n  }\n\n  // ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\xa6 应替换为:

\n
\nexport type IdType = 'Carta Identit\xc3\xa0' | 'Passaporto' | 'Patente'\n  \nexport type ODSModule = 'SCUOLA' | 'OPERATORI' | 'DRONI' | 'ODS_ROOT'\n\n// ...\n\nexport interface Address {\n  street: string;\n  city: string;\n  province: string;\n  CAP: string;\n}\n\n// ...\n
Run Code Online (Sandbox Code Playgroud)\n

然后,如果您喜欢这种方式,可以将模块作为名称空间导入:

\n
import * as Ods from "@revodigital/suiteods-types";\n
Run Code Online (Sandbox Code Playgroud)\n