您是否想知道如何自动生成打字稿代码?
使用Typescript编译器API,我们可以根据我们想要的任何规则来编写可以生成Typescript代码的脚本的函数!
要开始使用npm init
创建一个新项目,然后使用npm install typescript
安装“打字稿” NPM软件包。用touch index.mjs
创建一个文件index.mjs
,该文件将持有我们的代码生成脚本。
接下来,我们想弄清楚要生成哪种代码。对于此示例,我们将生成以下功能:
function add(a: number, b: number): number {
return a + b;
}
这是一个非常简单的示例,但是这些概念适用于您要生成的任何类型的代码。
在index.mjs
中,导入“打字稿”软件包,然后开始通过Intellisense探索其中的内容。在此示例中,我们看到我们需要定义一些“标识符”,特别是a
,b
和add
。这些都是“名称”,并由抽象语法树中的标识符表示。
我们可以使用称为createIdentifier
:
的工厂方法来定义文件顶部的每个标识符
const aId = ts.factory.createIdentifier("a");
const bId = ts.factory.createIdentifier("b");
const addId = ts.factory.createIdentifier("add");
我们还需要几次number
关键字,因此我们可以在其他下方添加它:
const numberKeyword = ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
然后,我们可以开始创建函数声明,并使用Intellisense弄清楚需要提供的内容:
const addFunc = ts.factory.createFunctionDeclaration(
/* modifiers */,
/* asteriskToken */,
/* name */,
/* typeParameters */,
/* parameters */,
/* type */,
/* body */
)
我们可以看到,对于不同类型的AST节点,它需要几个插槽。我们需要使用其中的一些,而其他我们可以用undefined
值留空。
前两个,modifiers
和asteriskToken
,我们可以在这里留空,因为我们在这里不需要它们。下一个name
我们可以使用我们之前定义的addId
。对于typeParameters
,我们可以留空。对于parameters
,我们需要使用已经创建的标识符来定义每个参数的两个,每个参数。对于type
,我们可以使用已经定义的numberKeyword
,这表示函数的返回类型。最后,对于身体,我们将创建一个新的块节点,该节点包含一个带有二进制表达式的返回语句,将两个参数添加在一起。
这里有很多技术术语 - 有关此处提到的所有内容的深入详细信息,请查看我的新书“ The Typescript Compiler API”,其中解释了从A-Z for代码生成,AST等等!
然后将其打印出来,我们可以通过:
使用printer
function print(nodes) {
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const resultFile = ts.createSourceFile(
"temp.ts",
"",
ts.ScriptTarget.Latest,
false,
ts.ScriptKind.TSX
);
console.log(printer.printList(ts.ListFormat.MultiLine, nodes, resultFile));
}
print([addFunc]);
最终脚本应该看起来像这样:
import ts from "typescript";
const aId = ts.factory.createIdentifier("a");
const bId = ts.factory.createIdentifier("b");
const addId = ts.factory.createIdentifier("add");
const numberKeyword = ts.factory.createKeywordTypeNode(
ts.SyntaxKind.NumberKeyword
);
const addFunc = ts.factory.createFunctionDeclaration(
undefined,
undefined,
addId,
undefined,
[
ts.factory.createParameterDeclaration(
undefined,
undefined,
aId,
undefined,
numberKeyword,
undefined
),
ts.factory.createParameterDeclaration(
undefined,
undefined,
bId,
undefined,
numberKeyword,
undefined
),
],
numberKeyword,
ts.factory.createBlock(
[
ts.factory.createReturnStatement(
ts.factory.createBinaryExpression(
aId,
ts.factory.createToken(ts.SyntaxKind.PlusToken),
bId
)
),
],
true
)
);
function print(nodes) {
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const resultFile = ts.createSourceFile(
"temp.ts",
"",
ts.ScriptTarget.Latest,
false,
ts.ScriptKind.TSX
);
console.log(printer.printList(ts.ListFormat.MultiLine, nodes, resultFile));
}
print([addFunc]);
运行node index.mjs
时,我们应该看到以下打印到控制台:
function add(a: number, b: number): number {
return a + b;
}
恭喜,您刚刚生成了第一个功能!如果您喜欢此练习,并想了解有关代码生成,抽象语法树,衬里,客户诊断等方面的更多信息,则可以随意查看我的new book,该new book涵盖了所有这些深入介绍。欢呼!