Yapay zeka ile JavaScript’ten TypeScript’e geçişte ajana “projeyi çevir” demezsin. Önce elindeki JavaScript’i kabul eden bir TypeScript ayarı kurarsın, sonra ajanlar dosyaları sabit bir sırayla çevirir; her adımın ne zaman bittiğine tip denetleyici ve testler karar verir. Derleyici, bir ajana verebileceğin en iyi gözden geçirendir: hızlıdır, yorulmaz ve “bence olmuş” diye ikna edilemez.
Bu rehber bu fikrin uygulamalı hâli: başlangıç için tam tsconfig.json, dosyaların sırasını nasıl seçeceğin, bir hafta kırmızı build görmeden strict ayarlarını nasıl sıkılaştıracağın, any’yi nasıl kontrol altında tutacağın, tip denetimini ajanın kendi doğrulama adımına nasıl çevireceğin ve işi birleştirme çakışması yaşamadan paralel ajanlara nasıl böleceğin. Eski kod refactor’ünün genel güvenlik ağı (karakterizasyon testleri, geri alma, inceleme) için önce yapay zeka ile eski kodu refactor etmek yazısını oku; burada tekrar etmiyoruz.
Sürüme bağlı ayrıntılar Ekim 2026 itibarıyla resmi TypeScript belgelerine göredir.
Ajanlar bu işte neden iyi
JS’ten TS’e geçiş büyük ölçüde mekanik bir iştir ve her adımın sonunda net bir sinyal vardır. Kodlama ajanlarının iyi olduğu iş tam olarak budur:
- Geri bildirim anında gelir.
tscdosyayı, satırı ve hata kodunu yazar. Ajan bunu okuyup tahmin etmeden düzeltebilir. - İş doğal olarak bölünür. Dosyalar ve klasörler tek tek çevrilebilir; iş birçok küçük, incelenebilir adıma ayrılır.
- Sıkıcı kısım çok büyüktür. Parametre tipleri eklemek, zaten var olan nesneler için interface yazmak ve
@typespaketleri kurmak, insanların yıllarca ertelediği türden iştir.
Risk de aynı derecede açık. Derleyiciyi yeşile çevirmesi beklenen bir ajan any’ye, as dönüşümlerine ve @ts-ignore’a uzanır, çünkü bunlar hataları yok eder. Bu rehberin büyük kısmı bu kaçış yollarını kapatmakla ilgili.
Adım 1: JavaScript’ini kabul eden bir tsconfig
İlk commit uygulama kodunda hiçbir şeyi değiştirmemeli. Yalnızca TypeScript’i ve tüm dosyalar hâlâ .js iken projeyi tip denetiminden geçiren bir ayarı ekler.
npm install --save-dev typescript @types/node
{
"compilerOptions": {
"allowJs": true,
"checkJs": false,
"strict": false,
"noEmit": true,
"incremental": true,
"target": "es2022",
"module": "nodenext",
"moduleResolution": "nodenext",
"types": ["node"],
"skipLibCheck": true
},
"include": ["src"]
}
Her seçimin yaptığı iş:
allowJs,.jsve.tsdosyalarının aynı programda yaşamasını sağlar; bir.tsdosyası.jsdosyasını içe aktarabilir, tersi de olur.checkJs: false, TypeScript’in henüz dokunmadığın dosyalarda hata raporlamasını engeller. Dosyaları tek tek dahil edeceksin.strict: falsebilinçli bir seçim. TypeScript 6.0’dan beristrictvarsayılan olaraktrue; yazmazsan ilk gün bütün strict denetimleri açılır.types: ["node"]aynı sebeple önemli: TypeScript 6.0’datypesvarsayılanı boş bir dizi, yani listelemezsen Node global’leri gelmez. Testlerin global’lere dayanıyorsa"jest"ya da"vitest/globals"ekle.noEmit, kodu zaten bir bundler,tsxya da framework’ün JavaScript’e çevirdiği ve TypeScript’in yalnızca denetlediği projelere uyar. Uygulamanıtscderliyorsa bunu kaldır veoutDirayarla.modulevemoduleResolution: Node uygulamaları içinnodenextkullan; bir bundler’ın derlediği kod için genellikle doğru ikili"module": "esnext"ile"moduleResolution": "bundler"dır.
Bir script ekle ve CI’ın çalıştırmasını sağla:
{
"scripts": {
"typecheck": "tsc -p tsconfig.json"
}
}
Bir kez çalıştır. checkJs kapalıyken bir JavaScript kod tabanında ya geçmeli ya da yalnızca birkaç ayar hatası göstermeli. Onları düzelt, commit’le; artık bir başlangıç noktan var. Bundan sonra “build yeşil” demek, npm run typecheck ve npm test’in ikisinin de geçmesi demek.
Adım 2: Yeniden adlandırmadan önce @ts-check ile hataları gör
Bir dosyayı yeniden adlandırmadan önce TypeScript’in onun hakkında ne düşündüğünü görebilirsin. Bir .js dosyasının ilk satırına // @ts-check ekle; TypeScript JSDoc yorumlarını tip olarak kullanarak o dosyadaki hataları raporlar:
// @ts-check
/**
* @param {number} cents
* @param {string} currency
* @returns {string}
*/
export function formatPrice(cents, currency) {
return new Intl.NumberFormat('en', { style: 'currency', currency }).format(cents / 100);
}
Büyük bir dosyada bu, ajan için iyi bir ilk iştir: “src/orders/pricing.js dosyasına // @ts-check ekle, hataları yalnızca JSDoc tipleriyle düzelt, davranışı değiştirme.” Yeniden adlandırmadan tip güvenliği kazanırsın ve sonraki dönüşüm neredeyse mekanik hâle gelir. Ters yaklaşımı seviyorsan checkJs: true yap ve henüz hazır olmayan dosyalara // @ts-nocheck koy; o satırı silmek adımın kendisi olur.
Adım 3: Sırayı seç, önce yapraklar
Önce kendi kodundan hiçbir şey içe aktarmayan dosyaları çevir, sonra yalnızca onları içe aktaranları ve böyle giriş noktalarına kadar devam et. Böylece çevirdiğin her dosya zaten var olan tiplere dayanabilir.
Sırayı elle çıkarmak zorunda değilsin. madge import grafiğini okur:
npx madge --leaves --extensions js,jsx src/
npx madge --circular --extensions js,jsx src/
--leaves bağımlılığı olmayan modülleri, --circular import döngülerini listeler. Döngüleri baştan bilmek işe yarar: bir döngüdeki dosyalar birlikte çevrilmek zorundadır, onları tek adım olarak planla.
Pratik bir gruplama kuralı: bir adım ya tek büyük bir dosyadır ya da küçük dosyalardan oluşan bir klasördür; diff’i tek oturuşta incelenebilecek kadar küçük olmalı. Listeyi MIGRATION.md gibi depoya eklenmiş bir dosyaya, her adım bir satır olacak şekilde yaz ve ajanların işaretlemesine izin ver. O dosya her ajan ve her oturum için ortak plan olur.
Adım 4: Tek dönüşüm promptu, tek bitti tanımı
Her adım için aynı prompt kalıbını kullan ki ajanlar kendi kurallarını uydurmasın:
Convert src/billing/ from JavaScript to TypeScript.
- Rename with git mv so history follows the files (.js -> .ts, .jsx -> .tsx).
- Add types for parameters, return values and exported objects.
Prefer types inferred from real usage over wide ones.
- Don't change runtime behaviour. No refactoring, no renaming,
no "while I'm here" fixes. If you find a bug, note it in
MIGRATION.md under "Found during migration" and leave it.
- No @ts-ignore, no @ts-nocheck. @ts-expect-error only with a reason
on the same line. No new `any` beyond the budget in .any-budget.
- Don't edit tsconfig.json, package.json or src/types/.
If you need a change there, stop and tell me what and why.
Done means: npm run typecheck passes, npm test passes,
npm run lint passes, and MIGRATION.md is updated.
Bu prompttaki iki satır işin çoğunu yapar. “Çalışma zamanı davranışını değiştirme” diff’i incelenebilir tutar, çünkü saf bir tip geçişi yalnızca tip açıklaması, yeniden adlandırma ve import ekler. “tsconfig.json’u düzenleme” ise yeşile giden en ucuz yolu, derleyiciyi gevşetmeyi kapatır.
Bu promptun değişmeyen kısımlarını CLAUDE.md ya da AGENTS.md içine koy ki her oturum onlarla başlasın; tek bir kural setini ajanlar arasında nasıl paylaşacağını CLAUDE.md nasıl yazılır anlatıyor.
Adım 5: Yalnızca azalan bir any bütçesi
Tek geçişte sıfır any’ye ulaşamazsın; doğrudan yasaklamak ise as unknown as Foo gibi daha kötü kaçışlar doğurur. Bütçe daha dürüsttür: bir sayıya izin verirsin ve o sayı yalnızca düşer.
Önce any ve susturma yorumlarını typescript-eslint ile görünür yap:
// eslint.config.js (excerpt)
rules: {
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/ban-ts-comment': ['error', {
'ts-expect-error': 'allow-with-description',
'ts-ignore': true,
'ts-nocheck': true,
minimumDescriptionLength: 10,
}],
}
Bu seçeneklerle ban-ts-comment, @ts-ignore ve @ts-nocheck’i reddeder, @ts-expect-error’ı ise yalnızca en az on karakterlik yazılı bir gerekçeyle kabul eder. Zaten @ts-expect-error daha iyi bir kaçış: hata düzeltildiğinde yorumun kendisi hataya dönüşür, yani bayatlayamaz.
Sonra açık any sayısını say ve depoda tutulan bir sayıyla karşılaştır:
#!/usr/bin/env bash
# scripts/any-budget.sh
count=$(npx eslint src --format json \
| node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const r=JSON.parse(s);console.log(r.flatMap(f=>f.messages).filter(m=>m.ruleId==="@typescript-eslint/no-explicit-any").length)})')
budget=$(cat .any-budget)
echo "explicit any: $count (budget $budget)"
[ "$count" -le "$budget" ] || { echo "any budget exceeded"; exit 1; }
Bunu CI’da ve ajanın bitti tanımında çalıştır. Bir adım sayıyı düşürdüğünde .any-budget değerini aynı commit’te düşür. Bütçenin nerede olduğunu ajana söyle; ajanlar bir sayıya, “mümkünse any kullanma” cümlesinden çok daha iyi uyar.
Sayımın yakalamadığı diğer kaçışlara dikkat et: dışarıdan gelen değerler (JSON.parse, istek gövdeleri) üzerinde as dönüşümleri, parametre tipi olarak Function ve object, ve her import’u any’ye çeviren bir declare module '*' satırı. İnceleyene, insan ya da ajan, diff’teki her yeni dönüşümü listelemesini söyle.
Adım 6: Tip denetimini ajanın doğrulama adımı yap
tsc çalıştırmadan “bitti” diyen bir ajan tahmin yürütüyordur. Denetimi, istemeyi hatırlaman gereken bir şey olmaktan çıkar ve ajanın turu bitirme biçiminin parçası yap.
Claude Code’da bir Stop hook’u, tip denetimi başarısızken turun bitmesini reddedebilir. Bunu .claude/hooks/typecheck.sh olarak kaydet:
#!/usr/bin/env bash
# Exit 2 sends stderr back to Claude and keeps it working.
input=$(cat)
if [ "$(echo "$input" | jq -r '.stop_hook_active')" = "true" ]; then
exit 0 # already retried once; let the turn end
fi
npx tsc -p tsconfig.json --pretty false 1>&2 || exit 2
ve .claude/settings.json içine kaydet:
{
"hooks": {
"Stop": [
{
"hooks": [
{ "type": "command", "command": ".claude/hooks/typecheck.sh" }
]
}
]
}
}
Bir Stop hook’u 2 koduyla çıktığında Claude Code durmaz ve hook’un stderr çıktısını Claude’a gösterir; ajan derleyici hatalarını görür ve düzeltmeye devam eder. stop_hook_active denetimi, döngüye girmek yerine turun ikinci denemede bitmesine izin verir. Hook’ları daha ayrıntılı Claude Code hooks rehberi anlatıyor. Edit|Write üzerinde bir PostToolUse hook’u her düzenlemeden sonra daha hızlı bir denetim çalıştırabilir, ama büyük projelerde her düzenlemede tam tsc yavaşlar.
Codex ve Gemini CLI, Claude’un hook’larını okumaz; aynı kuralı AGENTS.md ya da GEMINI.md içine yaz: “Bir işin bittiğini söylemeden önce npm run typecheck ve npm test çalıştır ve çıktının son satırlarını yapıştır.” Talimatı kalıcı yapan, çıktıyı istemektir.
Adım 7: Strict ayarlarını bayrak bayrak artır
Tüm dosyalar ya da bir alan .ts olduğunda, strict denetimlerini bu sırayla aç; her biri için ayrı commit ve ayrı ajan görevi olsun:
noImplicitAny: her parametre ve değişkenin bilinen bir tipi olmalı. En çok hatayı ve en faydalı tipleri bu üretir.strictNullChecks:nullveundefinedkendi tipleri olur. Bu, gerçek hataları, “undefined’ın özelliği okunamıyor” türünü bulur.- Strict ailesinin geri kalanı:
strictFunctionTypes,strictBindCallApply,strictPropertyInitialization,noImplicitThis,useUnknownInCatchVariables. Her biri genelde daha az hata çıkarır. "strict": true, hepsi geçtiğinde tek tek bayrakların yerini alır.strict’in parçası olmayan isteğe bağlı ekler:noUncheckedIndexedAccess(indeksle okunan değerundefinedolabilir) veexactOptionalPropertyTypes.
Bir bayrağı tüm depo için aynı anda açmak zorunda değilsin. İlk ayarı genişleten ve yalnızca bitmiş klasörleri kapsayan ikinci bir ayar, strict kodu strict tutarken geri kalanın yetişmesine izin verir:
{
"extends": "./tsconfig.json",
"compilerOptions": { "strict": true },
"include": ["src/billing", "src/utils"]
}
Bunu tsconfig.strict.json olarak kaydet ve CI’da ana denetimin yanında tsc -p tsconfig.strict.json çalıştır. Bir ajan bir klasörü bitirdiğinde klasörü include’a ekler. include tüm src’yi kapsadığında strict: true’yu ana ayara taşı ve ikinci dosyayı sil.
strictNullChecks için bir uyarı: “undefined olabilir” hatasının en hızlı düzeltmesi non-null assertion !’dir. Birkaç tane sorun değil; düzinelercesi ajanın sorunu sakladığı anlamına gelir. Bunun yerine bir kontrol, varsayılan değer ya da tip değişikliği iste ve incelemede yeni !’leri yeni any gibi değerlendir.
Adım 8: İşi paralel ajanlara böl
Geçiş, aynı anda birkaç ajan çalıştırmanın gerçekten karşılığını verdiği az sayıdaki işten biridir, çünkü klasörler büyük ölçüde bağımsızdır. Bunu çalıştırmanın yolu işi dizin bazında bölmek ve her ajana kendi git worktree’sini vermektir:
git worktree add ../app-ts-billing -b ts/billing
git worktree add ../app-ts-orders -b ts/orders
git worktree add ../app-ts-users -b ts/users
Her klasörde, yukarıdaki adım promptuyla ve kendi dizinine yönlendirilmiş bir ajan başlat. Birkaç kural dalların çakışmasını önler:
- Ortak dosyaların tek sahibi olur.
tsconfig.json,package.json, lock dosyası,eslint.config.jsvesrc/types/içindeki ortak bildirimler yalnızca ana dalda, senin ya da tek bir koordinatör ajanın elinde değişir. Klasör ajanları orada değişiklik yapmak yerine değişiklik ister. - Ortak tipler önce gelir. Birkaç klasör aynı
Userya daOrdertipine ihtiyaç duyuyorsa bunu paralel adımlardan önce sıralı bir adım yap. Aksi hâlde üç ajan birbirinden biraz farklı üçUserinterface’i yazar. @typespaketlerini merkezden kur. Her biri farklı bir paket ekleyen iki dal lock dosyasını yeniden yazar ve her seferinde çakışır.- Bir döngüyü paralelleştirme. Birbirini döngüsel olarak içe aktaran klasörler tek ajana aittir.
- Dalları tek tek birleştir ve her birleştirmeden sonra tip denetimi yap. İki dal ayrı ayrı
tsc’den geçip birlikte başarısız olabilir; örneğin biri diğerinin dayandığı dışa aktarılan bir tipi değiştirdiğinde. Sıradaki dalı birleştirmeden önce yeni ana dalın üzerine rebase et.
Kurulumu ve temizliği ayrıntılı olarak git worktree ile paralel geliştirme anlatıyor. Üç ya da dört ajan mantıklı bir başlangıçtır; bunun ötesinde darboğaz genellikle dalları yazmak değil, incelemek olur.
Adım 9: Hiçbir şeyin değişmediğini testler kanıtlasın
Tipler kodun kendi içinde tutarlı olduğunu söyler. Hâlâ eskiden yaptığını yaptığını yalnızca testler söyler. Geçiş sırasında:
- Her adımdan sonra tüm test takımını çalıştır, yalnızca çevrilen klasörün testlerini değil. Değişen bir dışa aktarım başka bir yerdeki çağıranı bozabilir.
- Test dosyalarını test ettikleri koddan sonra çevir, ayrı bir adımda; çevirirken beklenen değerleri değiştirme. “Yalnızca tip” commit’inde beklenen değeri değişmiş bir test kırmızı bayraktır.
- Test çalıştırıcının
.tsdosyalarını işlediğini kontrol et. Vitest TypeScript dosyalarını ek ayar olmadan çalıştırır; Jest isets-jestya da TypeScript ön ayarlıbabel-jestgibi bir dönüştürücüye ihtiyaç duyar. - Tiplerin ulaşmadığı yerlere test ekle. Girdi ayrıştıran, bir API ile konuşan ya da ortam değişkenlerini okuyan kod, tipler ne derse desin çalışma zamanında
anybiçimli veri alır. Oradaki birkaç test kusursuz tip açıklamalarından daha değerlidir. Ajanlara faydalı testler yazdırmayı yapay zeka ile test yazmak anlatıyor.
Sık yapılan hatalar
require’ıimport’a çevirmek anlamı değiştirir. Varsayılan dışa aktarımlar,module.exports = fnve birlikte çalışma CommonJS ile ES modülleri arasında farklıdır. Modül biçimi değişikliğini kendi adımı olarak tut ya da geçişin tamamen dışında bırak.- Yalan söyleyen tipler. Tek bir örnek nesneden yazılan bir interface, yalnızca bazen görünen alanları kaçırabilir. Gerçek veriden ya da API şemasından yazılmış tipleri tercih et.
- Tip commit’ine gizlenmiş davranış “düzeltmeleri”.
==’nin===olması, eklenen bir varsayılan parametre, sırası değişen birif. Her biri davranışı değiştirebilir. Reddet ve ayrı bir commit iste. - Derleyiciyi ayarla susturmak.
skipLibChecksorun değil; bir dalı geçirmek için strict bayrağını kapatmak sorun. Ajanlarıntsconfig.json’u düzenleyememesinin sebebi bu. - Üretilmiş ya da dışarıdan alınmış dosyalar. Ajana onları “tiplendirtmek” yerine
tsconfig.jsoniçinde hariç tut.
AgentVera ile yapmak
AgentVera, proje başına Claude Code, Codex, Gemini CLI ve diğer CLI ajanlarını yan yana çalıştırır; bu da birçok küçük adıma bölünmüş bir geçişe uyar.
- Klasör başına bir worktree. Git panelinden her dizin için bir worktree oluştur ve tek tıkla içinde bir ajan başlat; istersen bir klasörde Claude Code, diğerinde Codex.
- Dosya sahipliği.
tsconfig.json,package.jsonvesrc/types/**alanlarını koordinatör ajana ver. O çalışırken diğer ajanların bu dosyalara düzenlemeleri daha gerçekleşmeden reddedilir ve sahibine sormaları söylenir; Claude Code ajanlarını bir hook durdurur, diğer CLI’lar kuralı talimatlarında alır. - Verify. Mesajına “typecheck geçer, testler geçer, hiçbir test beklentisi değişmedi” yaz. Tur bittiğinde dosya düzenleyemeyen ayrı bir doğrulayıcı izinli test komutlarını çalıştırır, diff’i okur ve her ölçütü kanıtıyla geçti ya da kaldı olarak işaretler.
- Kod incelemesi. İkinci bir model biten her turu okur ve bulguları dosya:satır ile listeler; yeni dönüşümleri ve
!kullanımlarını yakalamak için iyi bir yer. - Birleştirme kuyruğu. Klasör dalları en güncel ana dalın üzerine tek tek iner ve
npm run typecheck && npm testgibi denetim komutun, bir şey birleştirilmeden önce birleşmiş sonuç üzerinde çalışır. - Paralel ekip (Pro ve Team). Bir ajan geçişi, her parçanın dokunabileceği dosyalarla birlikte en fazla sekiz parçaya bölebilir, her parçayı kendi worktree’sinde çalıştırır, biten parçaları tek bir entegrasyon dalında birleştirir ve son denetimi çalıştırır; sen tek bir pull request incelersin.
Toparlarken
Yapay zeka ile JavaScript’ten TypeScript’e geçiş, ajanın kendinden eminliği değil derleyici ve testler söz sahibi olduğunda işler. JavaScript’i kabul eden ve strict: false’u bilerek ayarlayan bir ayarla başla, küçük adımlarla önce yaprakları çevir, any’yi yalnızca küçülen bir bütçede tut, tsc’yi ajanın çıkış denetimi yap, strict ayarlarını bayrak bayrak artır ve paralel işi, ortak dosyaları tek bir ajana ait olacak şekilde dizin bazında böl. Her adım sıkıcı ve incelenebilir olur; bir geçişten istediğin de tam olarak bu.
Geçiş sırasında ajanları adım adım izleyeceksen, ajanın ne zaman sürmesine izin vereceğini ve ne zaman her adımı inceleyeceğini yapay zeka ile eşli programlama anlatıyor.