Meydan okuma 4: Mini derleyici
- TypeScript kursu
- İleri seviye
- Ders 57/57
- 6 dk
İleri seviyenin tamamını yoklayan bir görev çözersin.
Mini derleyici: AST + guard + exhaustive
İleri seviyenin özeti: discriminated union ile bir AST modelle, type guard ve switch ile daralt, never ile exhaustive kontrol yap ve recursive türle ifade ağacını kur. Bu dört parça birlikte derleme zamanında güvenli, çalışma zamanında doğru çalışan bir mini derleyici verir.
type Expr =
| { kind: "num"; value: number }
| { kind: "add"; left: Expr; right: Expr };
function evalE(e: Expr): number {
switch (e.kind) {
case "num": return e.value;
case "add": return evalE(e.left) + evalE(e.right);
}
}Yeni bir düğüm türü eklersen never kontrolü tüm switch'leri güncellemeye zorlar.
Uygulama İfade değerlendirici
Expr discriminated union'ını yaz: num (value: number), add (left, right: Expr), mul (left, right: Expr). evalE(e: Expr): number fonksiyonunu switch ile yaz ve default dalında const _: never = e ile exhaustive kontrol yap. (1 + 2) * 3 ifadesini kur ve sonucu yazdır.
Başlangıç kodu
// Expr: num | add | mul (discriminated union, recursive)
// evalE(e: Expr): number — switch ile daralt, never ile exhaustive yap
// (1 + 2) * 3 ifadesini kur ve sonucu yazdırÖrnek çözüm
type Expr =
| { kind: "num"; value: number }
| { kind: "add"; left: Expr; right: Expr }
| { kind: "mul"; left: Expr; right: Expr };
function evalE(e: Expr): number {
switch (e.kind) {
case "num":
return e.value;
case "add":
return evalE(e.left) + evalE(e.right);
case "mul":
return evalE(e.left) * evalE(e.right);
default:
const _: never = e;
throw new Error("exhaustive");
}
}
const expr: Expr = { kind: "mul", left: { kind: "add", left: { kind: "num", value: 1 }, right: { kind: "num", value: 2 } }, right: { kind: "num", value: 3 } };
console.log(evalE(expr));Beklenen çıktı
9
Uygulama Type guard ile değerlendir
Aynı Expr union'ını yaz. isNum(e: Expr): e is { kind: "num"; value: number } type guard'ını tanımla. evalE içinde önce isNum(e) ile daralt, sonra add ve mul için işlem yap. 5 + 10 ifadesini kur ve sonucu yazdır.
Başlangıç kodu
// Expr discriminated union (num | add | mul)
// isNum(e: Expr): e is { kind: "num"; value: number } type guard'ı yaz
// evalE içinde isNum ile daralt, toplamı yazdır
// add(5, num(10)) → 15Örnek çözüm
type Expr =
| { kind: "num"; value: number }
| { kind: "add"; left: Expr; right: Expr }
| { kind: "mul"; left: Expr; right: Expr };
function isNum(e: Expr): e is { kind: "num"; value: number } {
return e.kind === "num";
}
function evalE(e: Expr): number {
if (isNum(e)) return e.value;
if (e.kind === "add") return evalE(e.left) + evalE(e.right);
return evalE(e.left) * evalE(e.right);
}
const expr: Expr = { kind: "add", left: { kind: "num", value: 5 }, right: { kind: "num", value: 10 } };
console.log(evalE(expr));Beklenen çıktı
15
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 `never` ile yapılan exhaustive kontrol neyi garanti eder?
- Tüm case'ler `return` içerir
- Switch sonsuz döngüye girmez
- Yeni varyant eklenirse derleme hatası verir Doğru cevap
- Fonksiyon daha hızlı çalışır
Açıklama: Exhaustive `never` kontrolü, union'a yeni bir varyant eklendiğinde ama `switch` güncellenmediğinde derleme hatası verir; böylece unutulan case'ler erkenden yakalanır.
2 Exhaustive değişkeni
function evalE(e: Expr): number {
switch (e.kind) {
case "num": return e.value;
case "add": return evalE(e.left) + evalE(e.right);
default:
const _: ____ = e;
throw new Error("exhaustive");
}
}
function evalE(e: Expr): number {
switch (e.kind) {
case "num": return e.value;
case "add": return evalE(e.left) + evalE(e.right);
default:
const _: never = e;
throw new Error("exhaustive");
}
}
Açıklama: Exhaustive kontrol için değişken `never` türünde olmalı; ancak `e` gerçekten `never`'a daraldıysa atanır. `any` veya `unknown` kontrolü anlamsız kılar.
3 Derleyici parçaları
| Kavram | Anlamı |
|---|---|
Discriminated union |
AST düğüm türleri |
switch + case |
tür daraltma |
never |
exhaustive kontrol |
Recursive type |
iç içe ifade ağacı |