我正在尝试创建一个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加载器生成TypeScript代码?
{
"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"
}
}
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",
},
]
},
};
module.exports = function(source) {
return `
interface DummyContent {
name: string;
age?: number;
}
`;
};
import * as foo from './example';
console.log(foo);
{}
我认识到还有其他代码生成技术。例如,我可以使用一些构建工具将我的JSON文件转换为TypeScript并检查它们。我正在寻找一个更动态的解决方案。
my-own-loader.js不会导出json而是导出字符串。
这是正确的,就像加载图像文件并不总是导出二进制数据,但有时会输出表示图像元数据的JavaScript数据结构。
为什么需要从json文件定义typescript接口?接口是否用于打字稿编译?
是。我想导入一个描述我的API数据结构的文件,并自动生成相应的TypeScript接口。拥有共享文件允许前端和后端始终就将要出现的数据达成一致。
答案 0 :(得分:6)
首先,赞成提供MCVE。这是真正有趣的问题。我使用的代码将这个答案放在一起是基于所说的MCVE和is available here。
缺少文件?
这确实是一个无用的错误消息。该文件显然位于该位置,但TypeScript将拒绝加载任何没有可接受扩展名的文件。
此错误实质上隐藏了真实错误,即
TS6054: File 'c:/path/to/project/example.api' has unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts', '.js', '.jsx'.
这可以通过入侵typescript.js
并手动添加文件来验证。这很丑陋,因为侦探工作经常是(从第2.6.1节第95141行开始):
for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) {
var fileName = rootFileNames_1[_i];
this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName));
}
this.createEntry("c:/path/to/project/example.api", ts.toPath("c:/path/to/project/example.api", this.currentDirectory, getCanonicalFileName));
从概念上讲,您只是在加载程序之间传递一个字符串,但事实证明文件名 非常重要。
可能的解决方法
我没有看到使用awesome-typescript-loader
执行此操作的方法,但如果您愿意使用ts-loader
,您当然可以从具有任意扩展名的文件生成TypeScript,编译该TypeScript,并将其注入output.js
。
ts-loader
有一个appendTsSuffixTo
option,可以用来解决众所周知的file extension pain。如果您走这条路线,您的webpack配置可能会显示like this:
rules: [
{
test: /\.api$/,
exclude: /node_modules/,
use: [
{ loader: "ts-loader" },
{ loader: "my-own-loader" }
]
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: "ts-loader",
options: {
appendTsSuffixTo: [/\.api$/]
}
}
]
关于接口和DX的注意事项
接口被编译器擦除。这可以通过对this
之类的内容运行tsc
来证明
interface DummyContent {
name: string;
age?: number;
}
VS。 this
interface DummyContent {
name: string;
age?: number;
}
class DummyClass {
printMessage = () => {
console.log("message");
}
}
var dummy = new DummyClass();
dummy.printMessage();
为了提供良好的开发人员体验,您可能只需要将这些接口编写到dev环境中的文件中。您不需要将它们写出来用于生产构建,并且您不需要(或想要)将它们检入版本控制。
开发人员可能需要将它们写出来,以便他们的IDE能够深入研究。您可以将*.api.ts
添加到.gitignore
,并将其保留在存储库之外,但我怀疑他们是否需要存在于开发人员中。工作区。
例如,在我的样本仓库中,新开发人员必须运行npm install
(像往常一样)和 npm run build
(以在其本地环境中生成接口)摆脱他们所有的红色波浪形。
答案 1 :(得分:-1)
如果您的API遵循swagger规范,您可以使用npm包swagger-ts-generator从中生成TypeScript文件:
Swagger TypeScript代码生成器
Node模块为Angular生成TypeScript代码(2及以上) 基于Swagger v2格式的Webapi元数据。
基本上,你给它一个swagger URL并生成TypeScript。这些示例适用于Gulp,但它们应该很好地移植到WebPack:
<video>