我试图创建一个webpack加载器,将包含API数据结构描述的文件转换为一组TypeScript接口。
在我的具体案例中,文件是JSON,但这最终应该是无关紧要的-文件只是描述Web应用程序后端和前端之间交互的共享数据源。在下面的MCVE中,您可以看到JSON文件包含一个空对象,以强调文件的类型和内容与问题无关。
我目前的尝试报告了两个错误(我假设第二个错误是由第一个错误引起的):
[at-loader]: Child process failed to process the request: Error: Could not find file: '/private/tmp/ts-loader/example.api'.
ERROR in ./example.api
Module build failed: Error: Final loader didn't return a Buffer or String
如何使用webpack loader生成TypeScript代码?
package.json
{
"name": "so-example",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "webpack"
},
"dependencies": {
"awesome-typescript-loader": "^3.2.3",
"typescript": "^2.6.1",
"webpack": "^3.8.1"
}
}
webpack.js
const path = require('path');
module.exports = {
entry: './index.ts',
output: {
filename: 'output.js',
},
resolveLoader: {
alias: {
'my-own-loader': path.resolve(__dirname, "my-own-loader.js"),
},
},
module: {
rules: [
{
test: /\.api$/,
exclude: /node_modules/,
use: ["awesome-typescript-loader", "my-own-loader"],
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: "awesome-typescript-loader",
},
]
},
};
my-own-loader.js
module.exports = function(source) {
return `
interface DummyContent {
name: string;
age?: number;
}
`;
};
index.ts
import * as foo from './example';
console.log(foo);
example.API
{}
我认识到还有其他的代码生成技术。例如,我可以使用一些构建工具将JSON文件转换为TypeScript并将其检入。我在寻找一个更有活力的解决方案。
my-own-loader.js不会导出json,而是字符串。
这是正确的,就像加载图像文件并不总是导出二进制数据,但有时会输出表示图像元数据的JavaScript数据结构。
为什么需要从json文件定义typescript接口?这些接口会被用于类型脚本编译吗?
是。我想导入一个描述我的API数据结构的文件,并自动生成相应的TypeScript接口。拥有一个共享文件允许前端和后端总是同意将存在什么数据。
4条答案
按热度按时间pdtvr36n1#
首先,提供MCVE的荣誉。这是一个非常有趣的问题。我使用的代码将这个答案放在一起是基于MCVE和is available here。
文件丢失?
这确实是一个最无益的错误信息。该文件显然位于该位置,但TypeScript将拒绝加载任何不具有可接受扩展名的内容。
这个错误本质上隐藏了真实的错误,
这可以通过入侵
typescript.js
并手动添加文件来验证。它很难看,就像侦探工作经常做的那样(从v2.6.1中的第95141行开始):从概念上讲,您只是在加载器之间传递一个字符串,但事实证明文件名**在这里很重要。
可能的解决办法
我没有看到用
awesome-typescript-loader
实现这一点的方法,但是如果你愿意使用ts-loader
,你当然可以从具有任意扩展名的文件中生成TypeScript,编译该TypeScript,然后将其注入到你的output.js
中。ts-loader
有一个appendTsSuffixTo
选项,可以用来解决众所周知的file extension pain。你的webpack配置可能看起来像like this,如果你走的是这个路线:接口和DX注意事项
接口被编译器擦除。这可以通过对类似this的对象运行
tsc
来演示与this相比
为了提供良好的开发人员体验,您可能只需要将这些接口写入开发环境中的文件。您不需要将它们写出来用于生产构建,也不需要(或不想)将它们签入版本控制。
开发人员可能需要把它们写出来,这样他们的IDE就有了可以使用的东西。您可以将
*.api.ts
添加到.gitignore
,并将它们保留在存储库之外,但我怀疑它们需要存在于开发人员的目录中。例如,在我的示例代码库中,一个新的开发人员必须运行
npm install
(像往常一样)和npm run build
(在本地环境中生成接口)来消除所有红色的波浪线。vatpfxk52#
我知道这是一个老问题,但我最近遇到了类似的问题,所以它仍然相关。
一种解决方法是将
declare module "*.api";
添加到index.d.ts
文件中。但这有一个失去类型安全性的巨大缺点,因为速记模块声明中的所有内容都是any
类型。所以你也可以不生成TypeScript接口来开始。我设法解决了它使用一些巫毒教,我不完全理解,但它似乎是工作。
package.json
请注意,我在撰写本文时使用的是所有内容的最新版本,并且使用
ts-loader
而不是弃用的awesome-typescript-loader
。webpack.config.ts
对
appendTsSuffixTo
的需求是有据可查的,这是必要的,但还不够。我发现了几乎没有文档记录的
ts-loader
的resolveModuleName
选项。通过浏览ts-loader
代码并观察函数的输入和输出,我设法拼凑出了您下面看到的自定义解析器函数。我们必须将.ts
扩展附加到resolvedFileName
,以欺骗TypeScript编译器接受该文件。注意,我们需要对两个规则使用
ts-loader
配置,因此我将其提取到一个变量中。tsconfig.json
我不知道为什么这是必需的,但没有它,我得到
TS18002: The 'files' list in config file 'tsconfig.json' is empty.
。my-own-loader.js
我添加了一个值来表明我们保留了类型安全。
index.ts
请注意,我导入的文件包括
.api
扩展名。也许可以更改resolveModuleName
函数,使其在没有扩展的情况下工作,但我没有这样做。实际上,我喜欢看到这里的扩展作为一个线索,一些特别的事情正在发生。arknldoa3#
如果你的API遵循swagger规范,你可以使用npm包swagger-ts-generator来生成TypeScript文件:
Swagger TypeScript代码生成器
Node模块基于Swagger v2格式的Webapi Meta数据为Angular(2及以上)生成TypeScript代码。
基本上,你给予它一个swagger URL,它就会生成TypeScript。这些示例是针对Gulp的,但它们应该很好地移植到WebPack:
mfuanj7w4#
我从Mike Patricks版本创建了一个分叉,它有一些优点。
从加载器中导出“抽象类”而不是类型或接口。
更好的开发者体验
https://github.com/gwynjudd/ts-generating-loader