MavionaMAVIONA
Ücretsiz Teklif Alın
Yazılım

TypeScript Neden Zorunlu? JavaScript'ten Geçiş Rehberi

Eray
11 Şubat 202615 dk
TypeScript Neden Zorunlu? JavaScript'ten Geçiş Rehberi

"TypeScript'e geçmeli miyiz?" sorusu artık geçerliliğini yitirdi. 2026'da doğru soru şu: "Neden hâlâ geçmedik?" Bu yazıda TypeScript'in neden artık bir tercih değil zorunluluk olduğunu, JavaScript'te karşılaşılan gerçek hataları ve adım adım geçiş stratejisini ele alıyoruz.

JavaScript'in Problemi: Runtime Hataları

JavaScript dinamik tipli bir dil. Bu esneklik küçük scriptlerde avantaj olsa da, büyüyen projelerde kabusa dönüşür.

Gerçek Dünya Hata Örnekleri

1. Undefined is not a function — Klasik JavaScript kabusun:

// JavaScript — runtime'da patlıyor
function getUser(id) {
  return fetch(`/api/users/${id}`)
    .then(res => res.json());
}

// Geliştirici user.name yerine user.username yazdı
// Kod review'da farkedilmedi, production'a çıktı
async function displayUser() {
  const user = await getUser(1);
  document.getElementById("name").textContent = user.username;
  // undefined — ama hata vermez, sadece "undefined" yazar
}
// TypeScript — derleme zamanında yakalar
interface User {
  id: number;
  name: string;
  email: string;
}

async function getUser(id: number): Promise<User> {
  const res = await fetch(`/api/users/${id}`);
  return res.json();
}

async function displayUser() {
  const user = await getUser(1);
  document.getElementById("name")!.textContent = user.username;
  // TS Error: Property 'username' does not exist on type 'User'.
  // Did you mean 'name'?
}

TypeScript, bu hatayı siz kodu kaydettiğiniz anda, IDE'de kırmızı çizgiyle gösteriyor. Production'a çıkması imkansız.

2. API Yanıt Uyumsuzluğu:

// JavaScript — API yanıtı değişirse ne olur?
// Backend ekibi "price" alanını "amount" olarak değiştirdi
// Frontend'de hiçbir hata vermez, sadece undefined gösterir
function displayProduct(product) {
  return `${product.name} - ${product.price} TL`;
  // "Laptop - undefined TL" — sessizce bozulur
}
// TypeScript — API tipi ile sözleşme
interface Product {
  id: string;
  name: string;
  amount: number; // "price" → "amount" olarak güncellendi
  currency: string;
}

function displayProduct(product: Product): string {
  return `${product.name} - ${product.price} TL`;
  // TS Error: Property 'price' does not exist on type 'Product'.
  // IDE anında 42 dosyada bu hatayı gösterir
}

3. Yanlış Tip ile Fonksiyon Çağrısı:

// JavaScript — sessizce yanlış çalışır
function calculateDiscount(price, discount) {
  return price * (1 - discount / 100);
}

// Geliştirici string gönderdi
calculateDiscount("100", "20");
// Sonuç: NaN veya beklenmeyen değer
// TypeScript — hatalı kullanımı engeller
function calculateDiscount(price: number, discount: number): number {
  return price * (1 - discount / 100);
}

calculateDiscount("100", "20");
// TS Error: Argument of type 'string' is not assignable to parameter of type 'number'.

Sayılarla TypeScript'in Etkisi

Araştırmalar ve sektörel veriler TypeScript'in etkisini net gösteriyor:

  • Airbnb: JavaScript'ten TypeScript'e geçişte hataların %38'inin TypeScript tarafından önlenebileceğini tespit etti
  • Bloomberg: TypeScript geçişi sonrası production bug sayısında %40 azalma raporladı
  • GitHub 2025 Raporu: TypeScript, JavaScript'i geçerek en popüler dil oldu
  • Stack Overflow 2025: Geliştiricilerin %73'ü TypeScript'i tercih ediyor
  • npm: Yeni paketlerin %85'i TypeScript desteğiyle yayınlanıyor

TypeScript'in Temel Faydaları

1. Otomatik Tamamlama ve Dökümantasyon

TypeScript ile IDE'niz (VS Code) mükemmel otomatik tamamlama sunar. Bir objenin hangi property'lere sahip olduğunu, bir fonksiyonun hangi parametreleri aldığını ve ne döndüğünü anında görürsünüz.

interface BlogPost {
  id: number;
  title: string;
  slug: string;
  content: string;
  tags: string[];
  publishedAt: Date | null;
  author: {
    name: string;
    avatar: string;
  };
}

// IDE otomatik tamamlama — post. yazdığınızda tüm alanları gösterir
function formatPost(post: BlogPost) {
  // post. → id, title, slug, content, tags, publishedAt, author
  // post.author. → name, avatar
  return `${post.title} by ${post.author.name}`;
}

2. Güvenli Refactoring

Bir fonksiyon adını, bir property ismini veya bir tipi değiştirdiğinizde, TypeScript tüm projede etkilenen yerleri anında gösterir. "Find and Replace" ile tahmin yürütmeye gerek yok.

3. Dokümantasyon Olarak Tipler

TypeScript tipleri, yaşayan dokümantasyon görevi görür:

// Fonksiyonun ne aldığı ve ne döndüğü açık
type OrderStatus = "pending" | "processing" | "shipped" | "delivered" | "cancelled";

interface CreateOrderInput {
  customerId: string;
  items: Array<{
    productId: string;
    quantity: number;
    unitPrice: number;
  }>;
  shippingAddress: Address;
  paymentMethod: "credit_card" | "bank_transfer" | "cash_on_delivery";
}

interface Order extends CreateOrderInput {
  id: string;
  status: OrderStatus;
  totalAmount: number;
  createdAt: Date;
}

async function createOrder(input: CreateOrderInput): Promise<Order> {
  // Fonksiyon imzası her şeyi anlatıyor
  // JSDoc yazmaya gerek yok
}

4. Union Types ve Discriminated Unions

TypeScript'in en güçlü özelliklerinden biri:

// API yanıtları için mükemmel pattern
type ApiResponse<T> =
  | { status: "success"; data: T }
  | { status: "error"; message: string; code: number }
  | { status: "loading" };

function handleResponse(response: ApiResponse<User>) {
  switch (response.status) {
    case "success":
      // TypeScript bilir: response.data User tipinde
      console.log(response.data.name);
      break;
    case "error":
      // TypeScript bilir: response.message ve response.code var
      console.error(`Hata ${response.code}: ${response.message}`);
      break;
    case "loading":
      // TypeScript bilir: sadece status var
      console.log("Yükleniyor...");
      break;
  }
}

5. Generics ile Yeniden Kullanılabilir Kod

// Herhangi bir veri tipiyle çalışan genel fonksiyonlar
function paginate<T>(items: T[], page: number, perPage: number): {
  data: T[];
  total: number;
  currentPage: number;
  totalPages: number;
} {
  const start = (page - 1) * perPage;
  const data = items.slice(start, start + perPage);

  return {
    data,
    total: items.length,
    currentPage: page,
    totalPages: Math.ceil(items.length / perPage),
  };
}

// TypeScript tipi otomatik çıkarır
const userPage = paginate(users, 1, 10);
// userPage.data → User[]

const productPage = paginate(products, 2, 20);
// productPage.data → Product[]

JavaScript'ten TypeScript'e Geçiş Stratejisi

Aşama 1: Hazırlık (1 hafta)

# TypeScript'i projeye ekleyin
npm install -D typescript @types/react @types/node

# tsconfig.json oluşturun — gevşek ayarlarla başlayın
npx tsc --init
{
  "compilerOptions": {
    "strict": false,
    "allowJs": true,
    "checkJs": false,
    "noEmit": true,
    "esModuleInterop": true,
    "moduleResolution": "bundler",
    "jsx": "preserve",
    "incremental": true,
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

Önemli: strict: false ile başlayın. İlk günden strict mode açmak, yüzlerce hata ile karşılaşmanıza ve motivasyon kaybetmenize neden olur.

Aşama 2: Kademeli Dönüşüm (2-4 hafta)

Strateji: Yeni dosyaları .ts/.tsx olarak oluşturun, mevcut .js dosyalarını kademeli olarak dönüştürün.

Öncelik sırası:

  1. Paylaşılan tipler — API yanıtları, veri modelleri için tip dosyaları oluşturun
  2. Utility fonksiyonlar — En çok kullanılan yardımcı fonksiyonları dönüştürün
  3. API katmanı — fetch wrapper'ları ve API istemcisini tip güvenli yapın
  4. Component'ler — Yaprak component'lerden başlayarak yukarı çıkın
// types/api.ts — merkezi tip tanımları
export interface User {
  id: string;
  name: string;
  email: string;
  role: "admin" | "user" | "editor";
  createdAt: string;
}

export interface PaginatedResponse<T> {
  data: T[];
  pagination: {
    page: number;
    perPage: number;
    total: number;
    totalPages: number;
  };
}

// lib/api.ts — tip güvenli API istemcisi
export async function fetchApi<T>(
  endpoint: string,
  options?: RequestInit
): Promise<T> {
  const res = await fetch(`${API_BASE_URL}${endpoint}`, {
    headers: { "Content-Type": "application/json" },
    ...options,
  });

  if (!res.ok) {
    throw new Error(`API Error: ${res.status}`);
  }

  return res.json();
}

// Kullanım — tam tip güvenliği
const users = await fetchApi<PaginatedResponse<User>>("/users?page=1");
// users.data → User[]
// users.pagination.totalPages → number

Aşama 3: Strict Mode (4-8 hafta)

Dönüşüm %80'e ulaştığında, tsconfig.json'da strict mode'u açın:

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true
  }
}

Strict mode şunları zorlar:

  • strictNullChecks: null ve undefined kontrolleri
  • noImplicitAny: Açık tip tanımı olmayan değişkenleri engeller
  • strictFunctionTypes: Fonksiyon parametre tiplerini katı kontrol eder

Araç Önerileri

Araç Kullanım
VS Code TypeScript'in en iyi IDE desteği
ESLint + typescript-eslint TypeScript'e özel lint kuralları
Prettier Otomatik kod formatlama
ts-prune Kullanılmayan export'ları tespit etme
type-coverage Tip kapsama oranını ölçme
zod Runtime tip validasyonu (API sınırları)

TypeScript + Next.js: Mükemmel Uyum

Next.js, TypeScript'i birinci sınıf vatandaş olarak destekler. Sayfa tipleri, API route tipleri ve konfigürasyon dosyaları tamamen tip güvenli:

// app/blog/[slug]/page.tsx — Next.js 16 + TypeScript
import { Metadata } from "next";
import { notFound } from "next/navigation";

interface Props {
  params: Promise<{ slug: string }>;
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params;
  const post = await getPost(slug);
  if (!post) return {};

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      type: "article",
      publishedTime: post.date,
    },
  };
}

export default async function BlogPostPage({ params }: Props) {
  const { slug } = await params;
  const post = await getPost(slug);
  if (!post) notFound();

  return (
    <article>
      <h1>{post.title}</h1>
      <time dateTime={post.date}>{formatDate(post.date)}</time>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </article>
  );
}

Sonuç

TypeScript, 2026'da JavaScript projelerinde standart haline geldi. Büyük şirketlerden freelance geliştiricilere kadar herkes geçiş yapıyor. Sebebi basit: daha az hata, daha hızlı geliştirme, daha kolay bakım. Geçişi ertelemek, biriktirilen teknik borcun artması demek.

Maviona olarak tüm projelerimizde TypeScript kullanıyoruz. Müşterilerimize teslim ettiğimiz kodun güvenilir, bakımı kolay ve hatasız olmasını sağlamak için bu bir zorunluluk.

Projenizi TypeScript'e taşımak veya sıfırdan TypeScript tabanlı bir proje başlatmak istiyorsanız, Maviona ile iletişime geçin.

Paylaş

Bu Konudaki Hizmetlerimiz

Profesyonel destek almak ister misiniz?

WhatsApp ile yazın