Вивчення внутрішньої частини компілятора TypeScript
Компілятор TypeScript, який часто називають tsc
, є одним із основних компонентів екосистеми TypeScript. Він перетворює код TypeScript у JavaScript, дотримуючись правил статичних типів. У цій статті ми зануримося у внутрішню роботу компілятора TypeScript, щоб краще зрозуміти, як він обробляє та перетворює код TypeScript.
1. Процес компіляції TypeScript
Компілятор TypeScript виконує серію кроків для перетворення TypeScript у JavaScript. Ось загальний огляд процесу:
- Розбір вихідних файлів у абстрактне синтаксичне дерево (AST).
- Прив'язка та перевірка типу АСТ.
- Видача вихідного коду JavaScript і декларацій.
Давайте розглянемо ці кроки більш детально.
2. Розбір коду TypeScript
Першим кроком у процесі компіляції є аналіз коду TypeScript. Компілятор бере вихідні файли, аналізує їх у AST і виконує лексичний аналіз.
Ось спрощене уявлення про те, як отримати доступ до AST і керувати ним за допомогою внутрішнього API TypeScript:
import * as ts from 'typescript';
const sourceCode = 'let x: number = 10;';
const sourceFile = ts.createSourceFile('example.ts', sourceCode, ts.ScriptTarget.Latest);
console.log(sourceFile);
Функція createSourceFile
використовується для перетворення необробленого коду TypeScript в AST. Об’єкт sourceFile
містить проаналізовану структуру коду.
3. Зв'язування та перевірка типу
Після синтаксичного аналізу наступним кроком є зв’язування символів у AST і виконання перевірки типу. Ця фаза гарантує, що всі ідентифікатори пов’язані з їхніми відповідними оголошеннями, і перевіряє, чи відповідає код правилам типу TypeScript.
Перевірка типу виконується за допомогою класу TypeChecker
. Ось приклад того, як створити програму та отримати інформацію про тип:
const program = ts.createProgram(['example.ts'], {});
const checker = program.getTypeChecker();
// Get type information for a specific node in the AST
sourceFile.forEachChild(node => {
if (ts.isVariableStatement(node)) {
const type = checker.getTypeAtLocation(node.declarationList.declarations[0]);
console.log(checker.typeToString(type));
}
});
У цьому прикладі TypeChecker
перевіряє тип оголошення змінної та отримує інформацію про тип із AST.
4. Код емісії
Після завершення перевірки типу компілятор переходить до фази випуску. Тут код TypeScript перетворюється на JavaScript. Залежно від конфігурації вихідні дані також можуть містити файли декларацій і вихідні карти.
Ось простий приклад того, як використовувати компілятор для створення коду JavaScript:
const { emitSkipped, diagnostics } = program.emit();
if (emitSkipped) {
console.error('Emission failed:');
diagnostics.forEach(diagnostic => {
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.error(message);
});
} else {
console.log('Emission successful.');
}
Функція program.emit
генерує вивід JavaScript. Якщо є якісь помилки під час випромінювання, вони фіксуються та відображаються.
5. Діагностичні повідомлення
Одним із ключових обов’язків компілятора TypeScript є надання значущих діагностичних повідомлень розробнику. Ці повідомлення генеруються як на етапі перевірки типу, так і на етапі видачі коду. Діагностика може містити попередження та помилки, допомагаючи розробникам швидко виявляти та вирішувати проблеми.
Ось як отримати та відобразити діагностику з компілятора:
const diagnostics = ts.getPreEmitDiagnostics(program);
diagnostics.forEach(diagnostic => {
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.log(`Error ${diagnostic.code}: ${message}`);
});
У цьому прикладі діагностика витягується з програми та друкується на консолі.
6. Перетворення TypeScript за допомогою API компілятора
API компілятора TypeScript дозволяє розробникам створювати власні перетворення. Ви можете змінити AST перед випуском коду, забезпечуючи потужні налаштування та інструменти для створення коду.
Ось приклад простого перетворення, яке перейменовує всі змінні на newVar
:
const transformer = (context: ts.TransformationContext) => {
return (rootNode: T) => {
function visit(node: ts.Node): ts.Node {
if (ts.isVariableDeclaration(node)) {
return ts.factory.updateVariableDeclaration(
node,
ts.factory.createIdentifier('newVar'),
node.type,
node.initializer
);
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
};
const result = ts.transform(sourceFile, [transformer]);
console.log(result.transformed[0]);
Це перетворення відвідує кожен вузол в AST і перейменовує змінні за потреби.
Висновок
Вивчення внутрішньої частини компілятора TypeScript забезпечує глибше розуміння того, як код TypeScript обробляється та перетворюється. Незалежно від того, чи хочете ви створити власні інструменти чи вдосконалити свої знання про те, як працює TypeScript, вивчення внутрішніх функцій компілятора може стати повчальним досвідом.