如何在 TypeScript (Node.js) 包中包含全局文件类型声明
How to include a global file type declaration in a TypeScript (Node.js) package
我正在开发一个我计划在 npmjs 上公开发布的包。我们称它为“文本包”吧。
我希望在安装该软件包时默认情况下,您可以直接导入 .txt
文件并获得正确的类型(开箱即用),如下所示:
import text from './file.txt'
text
变量将是 string
类型,因为包会定义它的类型,使用类似这样的东西(在 global.d.ts 中):
declare module '*.txt' {
export const text: string;
export default text;
}
如果我在我的包中包含 global.d.ts,并且我从这个包中导入了一些东西,那么我将在导入 .txt
文件时自动获得正确的类型。
但问题是有时我只需要导入一个 .txt
文件而不从“文本包”导入任何东西,这就是为什么我想知道是否有某种方式,因为你安装一个安装全局类型的包,不需要为要应用的类型导入任何其他内容。
换句话说,一旦您安装了我的“txt 包”,declare module '*.txt'
就会立即应用于我的整个项目。
有没有办法做到这一点,或者安装我的包的人必须声明他们自己的全局类型(例如,declarations.d.ts)才能全局导入 .txt
文件?
我知道即使导入类型有效,它仍然需要 Webpack 或其他捆绑器才能真正工作,但这个问题只是关于类型。
要捆绑全局类型,请执行以下操作。 form typescript
- 在 typeRoots 指定默认类型目录。 .e.g
"typeRoots": ["./src/types"]
.
- 在指定目录下创建文件
/src/types/global.d.ts
- 在
declare global {}
内的文件中声明您的类型,如果您还没有导出任何内容,请确保有 export {}
。
简短的回答是:
如果不导入引用类型的文件,TypeScript 不支持全局类型。
更多详情:
我发现这样做的一个例子是 Next.js - 在使用 npx create-next-app@latest --typescript
创建 TypeScript 应用程序时,您可以开始导入 *.css
文件(例如)并获得正确的类型。
我感到困惑的地方是我最初认为类型来自 next-env.d.ts
但即使我删除了文件,*.css
导入仍在 Visual Studio 代码中工作.但原因是 pages
目录中的一个文件正在导入 Next.js' index.d.ts
文件。
基本上,在 Visual Studio 代码中,一旦您在项目中的某处导入了一个类型,如果它是全局的,那么它就可以随处访问。
解决方法
那么当前的 TypeScript 功能可以做什么呢?要支持新的文件类型,您将需要一个文件加载器,例如 Webpack。合乎逻辑的做法是在文件加载器本身中添加对文件类型声明的引用。这样,只要您将文件加载器配置为能够导入文件,您就会继承类型:
- 在我们的包的源目录中创建一个
txt.d.ts
(例如 src
)——您可以为该文件使用任何名称,这并不重要
- 如果您使用的是 eslint,请添加一个条目以忽略类型文件(例如
'src/*.d.ts'
在您的 ignorePatterns
选项中
- 由于您要在源中添加一个不受
tsc
管理的 d.ts
文件,因此您需要添加一个脚本来执行以下操作:
- 将
txt.d.ts
复制到你的包的编译文件的目标目录中
- 将此行添加到包文件加载器的顶部(例如
loader/index.d.ts
: /// <reference types="../txt" />\r\n
- 这会将 link 声明文件放回包中。请注意,您可以添加this reference to your package.
此变通方法仅在您导入引用回声明的文件后才有效 - 这是让 TypeScript 知道此类型存在的唯一方法(请参阅 https://github.com/microsoft/TypeScript/issues/49124)。
另一种替代方法也可以是添加手动步骤(在自述文件中)以添加全局类型声明文件。
我正在开发一个我计划在 npmjs 上公开发布的包。我们称它为“文本包”吧。
我希望在安装该软件包时默认情况下,您可以直接导入 .txt
文件并获得正确的类型(开箱即用),如下所示:
import text from './file.txt'
text
变量将是 string
类型,因为包会定义它的类型,使用类似这样的东西(在 global.d.ts 中):
declare module '*.txt' {
export const text: string;
export default text;
}
如果我在我的包中包含 global.d.ts,并且我从这个包中导入了一些东西,那么我将在导入 .txt
文件时自动获得正确的类型。
但问题是有时我只需要导入一个 .txt
文件而不从“文本包”导入任何东西,这就是为什么我想知道是否有某种方式,因为你安装一个安装全局类型的包,不需要为要应用的类型导入任何其他内容。
换句话说,一旦您安装了我的“txt 包”,declare module '*.txt'
就会立即应用于我的整个项目。
有没有办法做到这一点,或者安装我的包的人必须声明他们自己的全局类型(例如,declarations.d.ts)才能全局导入 .txt
文件?
我知道即使导入类型有效,它仍然需要 Webpack 或其他捆绑器才能真正工作,但这个问题只是关于类型。
要捆绑全局类型,请执行以下操作。 form typescript
- 在 typeRoots 指定默认类型目录。 .e.g
"typeRoots": ["./src/types"]
. - 在指定目录下创建文件
/src/types/global.d.ts
- 在
declare global {}
内的文件中声明您的类型,如果您还没有导出任何内容,请确保有export {}
。
简短的回答是:
如果不导入引用类型的文件,TypeScript 不支持全局类型。
更多详情:
我发现这样做的一个例子是 Next.js - 在使用 npx create-next-app@latest --typescript
创建 TypeScript 应用程序时,您可以开始导入 *.css
文件(例如)并获得正确的类型。
我感到困惑的地方是我最初认为类型来自 next-env.d.ts
但即使我删除了文件,*.css
导入仍在 Visual Studio 代码中工作.但原因是 pages
目录中的一个文件正在导入 Next.js' index.d.ts
文件。
基本上,在 Visual Studio 代码中,一旦您在项目中的某处导入了一个类型,如果它是全局的,那么它就可以随处访问。
解决方法
那么当前的 TypeScript 功能可以做什么呢?要支持新的文件类型,您将需要一个文件加载器,例如 Webpack。合乎逻辑的做法是在文件加载器本身中添加对文件类型声明的引用。这样,只要您将文件加载器配置为能够导入文件,您就会继承类型:
- 在我们的包的源目录中创建一个
txt.d.ts
(例如src
)——您可以为该文件使用任何名称,这并不重要 - 如果您使用的是 eslint,请添加一个条目以忽略类型文件(例如
'src/*.d.ts'
在您的ignorePatterns
选项中 - 由于您要在源中添加一个不受
tsc
管理的d.ts
文件,因此您需要添加一个脚本来执行以下操作:- 将
txt.d.ts
复制到你的包的编译文件的目标目录中 - 将此行添加到包文件加载器的顶部(例如
loader/index.d.ts
:/// <reference types="../txt" />\r\n
- 这会将 link 声明文件放回包中。请注意,您可以添加this reference to your package.
- 将
此变通方法仅在您导入引用回声明的文件后才有效 - 这是让 TypeScript 知道此类型存在的唯一方法(请参阅 https://github.com/microsoft/TypeScript/issues/49124)。
另一种替代方法也可以是添加手动步骤(在自述文件中)以添加全局类型声明文件。