如何为多个包创建通用声明文件?

Eug*_*akh 2 typescript typescript-typings

我有一个项目,由多个包和一个通用包组成。我在每个包中都有完全相同的声明文件:

declare module '*.scss' {
  const styles: { [className: string]: string };
  export default styles;
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的目标是将此声明移至公共包或其他公共类型包,以便 TypeScript 在使用此公共包的每个包中自动识别它们。

有办法实现吗?

先感谢您!

Alu*_*dad 5

这个设置实际上相当简单。然而,正如我们将看到的,在使用共享声明时有多种选择。

\n

第 1 部分:创建共享包

\n

为了便于说明,我们将为我们的共享包起一个极具启发性的名称:shared-package,并由以下 5 个文件组成:

\n

包.json

\n
{\n  "name": "shared-package",\n  "version": "1.0.0",\n  "main": "index",\n  "types": "index",\n  "devDependencies": {\n    "typescript": "^3.9.7"\n  },\n  "scripts": {\n    "tsc": "tsc",\n    "prepare": "tsc"\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

tsconfig.json

\n
{\n  "compilerOptions": {\n    "strict": true,\n    "target": "ESNext", // adjust as necessary depending on your target platform/toolchain\n    "module": "ESNext", // adjust as necessary depending on your target platform/toolchain\n    "moduleResolution": "Node",\n    "declaration": true,\n    "esModuleInterop": true\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

环境模块.ts

\n
declare module \'*.scss\' {\n  const styles: {[className: string]: string};\n  export default styles;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

实用程序.ts

\n
export const \xcf\x80 = 3.142857142857143;\n\nexport interface Complex {\n  real: number;\n  imaginary: number;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

索引.ts

\n
import \'./ambient-modules\';\nexport * from \'./utilities\';\n
Run Code Online (Sandbox Code Playgroud)\n

第 2 部分:使用共享包

\n

为了便于说明,我们将创建一个简单的包,命名为consumer-package,它取决于shared-package我们上面描述的包,并由以下文件组成

\n

包.json

\n
{\n  "name": "consumer-package",\n  "version": "1.0.0",\n  "main": "index",\n  "types": "index",\n  "dependencies": {\n    "shared-package": "^1.0.0"\n  },\n  "devDependencies": {\n    "typescript": "^3.9.7"\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

tsconfig.json

\n
{\n  "compilerOptions": {\n    "strict": true,\n    "target": "ESNext", // adjust as necessary depending on your target platform/toolchain\n    "module": "ESNext", // adjust as necessary depending on your target platform/toolchain\n    "moduleResolution": "Node",\n    "esModuleInterop": true\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

应用程序.scss

\n
.app {\n  text-transform: capitalize;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

应用程序.ts

\n
import styles from \'./app.scss\';\n\nexport default {\n  styles,\n  template: `\n    <div class="app">\n      hello world\n    </div>\n  `\n};\n
Run Code Online (Sandbox Code Playgroud)\n

索引.ts

\n
import app from \'./app\';\n\nexport default function bootstrap() {\n  console.log(\'injecting styles: \', app.styles);\n  console.log(\'rendering markup: \', app.template);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然而,我们现在在上面的文件中遇到了一个错误app.ts,\n Cannot find module \'./app.scss\' or its corresponding type declarations.ts(2307),这是因为,虽然我们依赖于我们的共享包,但我们没有编写任何依赖于它的代码。

\n

我们已经在包级别完全建立了consumer-package依赖关系shared-package,但 TypeScript 还没有看到这种依赖关系。TypeScript 语言服务不会对我们的node_modules目录进行详尽的爬行,以查找包含可能包含在各种依赖项中的环境声明的文件。

\n

(如果这样做,冲突和意外错误很快就会出现)。

\n

有几种方法可以确保我们的环境模块声明declare module \'*.scss\' {...}被语言所接受。

\n
    \n
  1. 从任何源文件中shared-package导入任何内容consumer-package

    \n

    消费者包/index.ts

    \n
    import {Complex} \'shared-package\';\nimport app from \'./app\';\n
    Run Code Online (Sandbox Code Playgroud)\n
  2. \n
  3. 或导入shared-package其副作用

    \n

    消费者包/index.ts

    \n
    import \'shared-package\';\nimport app from \'./app\';\n
    Run Code Online (Sandbox Code Playgroud)\n

    注意:这使得所有类型和值都可用,但可能会干扰导入省略和树摇动等交付优化*

    \n
  4. \n
  5. 或使用三斜杠引用指令来明确声明您依赖于中的声明shared-package

    \n

    消费者包/index.ts

    \n
    /// <reference types="shared-package" />\n\nimport app from \'./app\';\n
    Run Code Online (Sandbox Code Playgroud)\n

    注意:这使得所有类型都不会干扰任何潜在的优化,但会降低源代码的可移植性,特别是与 NodeJS 和特定包管理器的行为更加耦合*

    \n
  6. \n
  7. 或调整您tsconfig.json以明确列出它所依赖的类型,包括shared-package.

    \n

    消费者包/tsconfig.json

    \n
    {\n  "compilerOptions": {\n    "strict": true,\n    "target": "ESNext",\n    "module": "ESNext",\n    "moduleResolution": "Node",\n    "esModuleInterop": true,\n    "types": [\n      "shared-package"\n    ]\n  }\n}\n
    Run Code Online (Sandbox Code Playgroud)\n

    注意:这使得所有类型都不会干扰任何潜在的优化,但会降低源代码的可移植性,特别是与 NodeJS 和特定包管理器的行为更加耦合。但是,与该方法相比,它具有主观优势/// <reference>,因为它要求您显式列出包含全局影响的类型级别依赖项(例如declare module \'m\'您自己的包本身需要的构造)的包

    \n
  8. \n
\n

所有这些方法都允许.scss在 中的任何位置键入文件导入,以一种或另一种方式通知consumer-packageTypeScript 。consumer-packageshared-package

\n

我的偏好是前两个选项中的任何一个。

\n

笔记:

\n

"dependencies"部分中consumer-package/package.json,对包的依赖关系shared-package指定为"shared-package": "shared-package"

\n

这假设它位于我们的包管理器的注册表中,如果它发布到https://npmjs.com ,则这是正确的。

\n

如果我们在发布到我们选择的注册表之前对此进行测试,我们可以直接使用文件系统

\n

假设shared-packageconsumer-package位于姐妹目录中:

\n
$ cd ./consumer-package\n$ npm install ../shared-package\n
Run Code Online (Sandbox Code Playgroud)\n

这将导致将其列为 的"dependencies"部分。其他包管理器,例如 JSPM 和 Yarn,支持相同的功能 - 有关详细信息,请参阅它们的文档。consumer-package/package.json"shared-package": "../shared-package"

\n