TypeScript'in Derleyici İç Yapısını Keşfetme
TypeScript'in derleyicisi, genellikle tsc
olarak adlandırılır ve TypeScript ekosisteminin temel bileşenlerinden biridir. Statik yazım kurallarını uygularken TypeScript kodunu JavaScript'e dönüştürür. Bu makalede, TypeScript derleyicisinin TypeScript kodunu nasıl işlediğini ve dönüştürdüğünü daha iyi anlamak için TypeScript derleyicisinin iç işleyişine dalacağız.
1. TypeScript Derleme Süreci
TypeScript derleyicisi, TypeScript'i JavaScript'e dönüştürmek için bir dizi adımı takip eder. İşte sürecin üst düzey bir genel bakışı:
- Kaynak dosyalarını Soyut Sözdizimi Ağacına (AST) ayrıştırma.
- AST'nin bağlanması ve tip denetimi.
- Çıkış JavaScript kodunu ve bildirimlerini yayınlamak.
Bu adımları daha detaylı inceleyelim.
2. TypeScript Kodunu Ayrıştırma
Derleme sürecindeki ilk adım TypeScript kodunu ayrıştırmaktır. Derleyici kaynak dosyalarını alır, bunları bir AST'ye ayrıştırır ve sözcüksel analiz gerçekleştirir.
TypeScript'in dahili API'sini kullanarak AST'ye nasıl erişebileceğiniz ve onu nasıl yönetebileceğiniz konusunda basitleştirilmiş bir görünüm şöyledir:
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
fonksiyonu ham TypeScript kodunu bir AST'ye dönüştürmek için kullanılır. sourceFile
nesnesi kodun ayrıştırılmış yapısını içerir.
3. Bağlama ve Tür Kontrolü
Ayrıştırmadan sonraki adım, sembolleri AST'ye bağlamak ve tür denetimi gerçekleştirmektir. Bu aşama, tüm tanımlayıcıların ilgili bildirimlerine bağlı olduğundan emin olur ve kodun TypeScript'in tür kurallarını takip edip etmediğini kontrol eder.
Tür denetimi TypeChecker
sınıfı kullanılarak gerçekleştirilir. İşte bir program oluşturma ve tür bilgilerini alma örneği:
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));
}
});
Bu örnekte, TypeChecker
bir değişken bildiriminin türünü kontrol eder ve AST'den tür bilgisini alır.
4. Kod Emisyonu
Tür denetimi tamamlandıktan sonra derleyici yayımlama aşamasına geçer. TypeScript kodunun JavaScript'e dönüştürüldüğü yer burasıdır. Çıktı, yapılandırmaya bağlı olarak bildirim dosyaları ve kaynak haritaları da içerebilir.
Derleyicinin JavaScript kodunu yayımlamak için nasıl kullanılacağına dair basit bir örnek:
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
fonksiyonu JavaScript çıktısını üretir. Yayılım sırasında herhangi bir hata varsa, bunlar yakalanır ve görüntülenir.
5. Tanı Mesajları
TypeScript derleyicisinin temel sorumluluklarından biri geliştiriciye anlamlı tanılama mesajları sağlamaktır. Bu mesajlar hem tür denetimi hem de kod yayımlama aşamalarında üretilir. Tanılamalar uyarıları ve hataları içerebilir ve geliştiricilerin sorunları hızla belirlemesine ve çözmesine yardımcı olur.
Derleyiciden tanılamaları nasıl alacağınız ve görüntüleyeceğiniz aşağıda açıklanmıştır:
const diagnostics = ts.getPreEmitDiagnostics(program);
diagnostics.forEach(diagnostic => {
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.log(`Error ${diagnostic.code}: ${message}`);
});
Bu örnekte, tanılamalar programdan çıkarılıp konsola yazdırılır.
6. Derleyici API'leri ile TypeScript'i Dönüştürme
TypeScript derleyici API'si geliştiricilerin özel dönüşümler oluşturmasına olanak tanır. Kod yayımından önce AST'yi değiştirebilir, güçlü özelleştirmeler ve kod oluşturma araçlarına olanak sağlayabilirsiniz.
İşte tüm değişkenleri newVar
olarak yeniden adlandıran basit bir dönüşümün örneği:
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]);
Bu dönüşüm AST'deki her düğümü ziyaret eder ve değişkenleri gerektiği gibi yeniden adlandırır.
Çözüm
TypeScript'in derleyici iç yapısını keşfetmek, TypeScript kodunun nasıl işlendiği ve dönüştürüldüğü konusunda daha derin bir anlayış sağlar. İster özel araçlar oluşturmak, ister TypeScript'in nasıl çalıştığına dair bilginizi geliştirmek isteyin, derleyicinin iç yapısını araştırmak aydınlatıcı bir deneyim olabilir.