Пользовательские преобразователи и генерация кода
Пишите преобразования компилятора, изменяющие AST
«Пользовательские преобразователи и генерация кода» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.
Что такое трансформеры
Трансформеры TypeScript — это функции, которые получают узел AST и возвращают узел, возможно изменённый. Они выполняются во время компиляции, чтобы создавать пользовательский результат.
import ts from "typescript";
type Transformer = ts.TransformerFactory<ts.SourceFile>;Структура фабрики трансформера
Фабрика трансформеров принимает TransformationContext и возвращает функцию, преобразующую узлы SourceFile.
const myTransformer: ts.TransformerFactory<ts.SourceFile> =
(ctx) => (sf) => {
function visit(node: ts.Node): ts.Node {
// Modify node here
return ts.visitEachChild(node, visit, ctx);
}
return ts.visitNode(sf, visit) as ts.SourceFile;
};Обход с контекстом
ts.visitEachChild (а не forEachChild) используется внутри трансформеров, поскольку корректно пересоздаёт изменённые узлы.
function visit(node: ts.Node): ts.Node {
if (ts.isStringLiteral(node)) {
return ts.factory.createStringLiteral(node.text.toUpperCase());
}
return ts.visitEachChild(node, visit, ctx);
}Создание новых узлов с помощью ts.factory
Объект ts.factory предоставляет методы для создания узлов AST всех видов.
const newCall = ts.factory.createCallExpression(
ts.factory.createIdentifier("console.log"),
undefined,
[ts.factory.createStringLiteral("hello")]
);Применение трансформеров к программе
Передайте трансформеры параметру customTransformers метода program.emit.
program.emit(undefined, undefined, undefined, false, {
before: [myTransformer],
});Генерация кода: печать узлов
Используйте ts.createPrinter, чтобы преобразовать узлы AST обратно в строки исходного кода без запуска полного компилятора.
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const result = printer.printNode(
ts.EmitHint.Unspecified,
newCall,
sf
);
console.log(result); // console.log("hello")Генерация целых исходных файлов
Вы можете создать полный исходный файл с нуля с помощью ts.factory.createSourceFile или собрать его из списка узлов операторов.
const statements = [
ts.factory.createExpressionStatement(
ts.factory.createCallExpression(
ts.factory.createIdentifier("console.log"),
undefined,
[ts.factory.createStringLiteral("generated!")]
)
),
];Преобразование импортов
Распространённый вариант использования — преобразование путей импорта, например замена псевдонимов путей на относительные пути во время вывода.
if (ts.isImportDeclaration(node)) {
const spec = node.moduleSpecifier as ts.StringLiteral;
if (spec.text.startsWith("@app/")) {
return ts.factory.updateImportDeclaration(
node, node.modifiers, node.importClause,
ts.factory.createStringLiteral(spec.text.replace("@app/", "../")),
node.assertClause
);
}
}Тестирование трансформеров
Тестируйте трансформеры, применяя их к небольшому исходному файлу и проверяя, что напечатанный результат совпадает с ожидаемой строкой.
const result = ts.transpileModule("const x = 'hello';", {
compilerOptions: { target: ts.ScriptTarget.ES2020 },
transformers: { before: [myTransformer] },
});
console.log(result.outputText);Системы плагинов
Некоторые инструменты сборки (например, ttypescript / ts-patch) позволяют регистрировать трансформеры как плагины в tsconfig, делая их работу незаметной для процесса разработки.
// tsconfig.json with ts-patch:
// "plugins": [{ "transform": "./my-transformer.js" }]Итоги: пользовательские трансформеры
Трансформеры позволяют переписывать код TypeScript на уровне AST во время компиляции. Используйте ts.visitEachChild для рекурсивного обхода, ts.factory для создания узлов и ts.createPrinter для генерации исходного текста.
Быстрая проверка
Какой объект используется для создания новых узлов AST в трансформере?
Что Вы узнали
Пользовательские трансформеры изменяют AST TypeScript во время компиляции. Используйте ts.visitEachChild для рекурсии, ts.factory для создания новых узлов и program.emit с customTransformers для их применения.
Часто задаваемые вопросы
Урок «Пользовательские преобразователи и генерация кода» бесплатный?
Да — полный текст урока «Пользовательские преобразователи и генерация кода» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Пользовательские преобразователи и генерация кода»?
Пишите преобразования компилятора, изменяющие AST Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать TypeScript Academy?
Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Пользовательские преобразователи и генерация кода»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке TypeScript Academy?
Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Создание программы TypeScript с помощью API
- Обход AST с помощью посетителей
- Пользовательские преобразователи и генерация кода
- Создание простого инструмента проверки стиля кода