Yapay zeka ile JavaScript’ten TypeScript’e geçiş

JavaScript’ten TypeScript’e yapay zeka ajanlarıyla güvenli geçiş: JS kabul eden tsconfig, dosya dosya sıra, kademeli strict, any bütçesi ve doğrulama adımı tsc.

Solviera Teknoloji 11 dk okuma

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. tsc dosyayı, 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 @types paketleri 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, .js ve .ts dosyalarının aynı programda yaşamasını sağlar; bir .ts dosyası .js dosyası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: false bilinçli bir seçim. TypeScript 6.0’dan beri strict varsayılan olarak true; yazmazsan ilk gün bütün strict denetimleri açılır.
  • types: ["node"] aynı sebeple önemli: TypeScript 6.0’da types varsayı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, tsx ya da framework’ün JavaScript’e çevirdiği ve TypeScript’in yalnızca denetlediği projelere uyar. Uygulamanı tsc derliyorsa bunu kaldır ve outDir ayarla.
  • module ve moduleResolution: Node uygulamaları için nodenext kullan; 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:

  1. noImplicitAny: her parametre ve değişkenin bilinen bir tipi olmalı. En çok hatayı ve en faydalı tipleri bu üretir.
  2. strictNullChecks: null ve undefined kendi tipleri olur. Bu, gerçek hataları, “undefined’ın özelliği okunamıyor” türünü bulur.
  3. Strict ailesinin geri kalanı: strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables. Her biri genelde daha az hata çıkarır.
  4. "strict": true, hepsi geçtiğinde tek tek bayrakların yerini alır.
  5. strict’in parçası olmayan isteğe bağlı ekler: noUncheckedIndexedAccess (indeksle okunan değer undefined olabilir) ve exactOptionalPropertyTypes.

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.js ve src/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ı User ya da Order tipine ihtiyaç duyuyorsa bunu paralel adımlardan önce sıralı bir adım yap. Aksi hâlde üç ajan birbirinden biraz farklı üç User interface’i yazar.
  • @types paketlerini 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 .ts dosyalarını işlediğini kontrol et. Vitest TypeScript dosyalarını ek ayar olmadan çalıştırır; Jest ise ts-jest ya da TypeScript ön ayarlı babel-jest gibi 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 any biç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 = fn ve 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 bir if. Her biri davranışı değiştirebilir. Reddet ve ayrı bir commit iste.
  • Derleyiciyi ayarla susturmak. skipLibCheck sorun değil; bir dalı geçirmek için strict bayrağını kapatmak sorun. Ajanların tsconfig.json’u düzenleyememesinin sebebi bu.
  • Üretilmiş ya da dışarıdan alınmış dosyalar. Ajana onları “tiplendirtmek” yerine tsconfig.json iç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.json ve src/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 test gibi 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.

Sık sorulanlar

Yapay zeka bir JavaScript projesini TypeScript’e çevirebilir mi?

Evet; çalışan bir tip denetleyici, sabit bir sıra ve küçük adımlar verdiğin sürece ajanların iyi yaptığı işlerden biridir. Ajan her seferinde bir dosya ya da klasör çevirsin, her adımdan sonra tsc ve testleri çalıştırsın ve her adım ayrı commit olsun.

Strict modu en baştan açmalı mıyım?

Var olan bir kod tabanında hayır. TypeScript 6.0’dan beri strict varsayılan olarak açık; bu yüzden başta "strict": false değerini açıkça yaz, dosyaları çevir, sonra noImplicitAny, strictNullChecks ve diğer strict bayraklarını tek tek aç.

Ajanın her yere any yazmasını nasıl engellerim?

Ölçülebilir hâle getir. Açık any kullanımını typescript-eslint’in no-explicit-any kuralıyla raporla, @ts-ignore’u ban-ts-comment ile yasakla, depoda bir bütçe sayısı tut ve sayı bunu aşınca CI’ı kır. Bütçeyi ajanın talimatlarına da yaz.

Birden fazla ajan farklı klasörleri aynı anda taşıyabilir mi?

Evet; her biri kendi git worktree’sinde çalışır ve bir dizinin sahibi olursa. tsconfig.json, package.json ve global tip bildirimleri gibi ortak dosyalar tek bir ajana ait olmalı ve her dal birleştirildikten sonra yeniden tip denetiminden geçmeli.

Geçiş sırasında testlerimi yeniden yazmam gerekir mi?

Hayır. Önce mevcut testleri çevrilen koda karşı çalıştırmaya devam et; davranışın değişmediğini sana söyleyen onlardır. Test dosyalarını test ettikleri modülden sonra çevir ve aynı adımda beklenen değerleri değiştirme.

Ajanlarını bir masaya topla.

AgentVera’yı ücretsiz indir; kurulu CLI’ların hazır.

Diğer yazılar