📌 Hızlı Özet:
TypeScript, Astro sitelerinde icerik semalari ve UI adaciklari icin erken hata yakalama saglar. Asıl olceklenebilirlik, strict ayar + dar domain tipleri + Python/servislerle paylasilan veri kontratlarindan gelir. Bu rehber “her yeri generic yap” demez; Pusula USV / yazilim muhendisligi bakisiyla nerede tip, nerede esneklik oldugunu anlatir.


Neden bu yazı Astro + interop odaklı?

TypeScript ogrenme kaynaklarinin cogu React SPA varsayar. Benim uretim kullanimim farkli: Astro SSG ile Markdown icerik, az sayida hydrate island, bazen kucuk API; diger yanda Python ile simülasyon, ROS 2 dugumleri, telemetri. Iki dil ayni surecte yasayinca tip guvenligi “TSConfig sihri” olmaktan cikıp sinir (boundary) muhendisligi olur.

Adim 0 — strict ve gercekci tsconfig

Yeni Astro projesinde TypeScript sablonu geliyorsa bile sunlari bilinçli secin:

  • strict: true
  • noUncheckedIndexedAccess: true (dizi/index surprizlerini azaltir)
  • exactOptionalPropertyTypes (ileri seviye; ekibe gore)
  • skipLibCheck: true (bagimlilik tipleriyle savasmamak icin pratik)

Amac, derleyicinin “her seyi any’ye cevirmeme” konusundaki yardimini acmak. Performans garantisi yok; garantiledigi sey, bir sinif bug’unun build’de patlamasidir.

Icerik katmani: Collection semalari

Astro content collections, Markdown frontmatter’ini Zod (veya benzeri) ile dogrular. Bu, blog motorunda tip guvenliginin en yuksek kaldiracidir:

import { defineCollection, z } from "astro:content";

const articles = defineCollection({
  type: "content",
  schema: z.object({
    title: z.string().min(8),
    description: z.string().min(40),
    publishDate: z.coerce.date(),
    author: z.string(),
    category: z.enum([
      "Guvenlik",
      "Web & SEO",
      "Bulut & Mimari",
      "Yazilim Gelistirme",
      "Yapay Zeka",
      "Robotik",
    ]),
    tags: z.array(z.string()).min(1),
    featured: z.boolean().default(false),
    contentOrigin: z.enum(["original", "scaffold", "translated"]),
    reviewed: z.boolean(),
  }),
});

export const collections = { articles };

Yanlis category veya eksik reviewed artik “sessizce yayina girmez”; build kirilir. Bu, AdSense odakli icerik sitelerinde kalite kapisidir.

Domain tipleri: string’i her yere yaymayın

string ile her seyi modellemek, JavaScript’e geri donmektir. Daraltın:

type ArticleSlug = string & { readonly __brand: "ArticleSlug" };
type IsoDateString = string & { readonly __brand: "IsoDateString" };

type PublishState = "draft" | "review" | "published";

type ArticleMeta = {
  slug: ArticleSlug;
  state: PublishState;
  publishDate: Date;
};

Brand type abartilabilir; ama state: string yerine union kullanmak tek basina cok sey kurtarir. Discriminated union’lar UI’da da ise yarar:

type LoadResult =
  | { status: "ok"; data: ArticleMeta }
  | { status: "not_found" }
  | { status: "error"; message: string };

function titleOf(result: LoadResult): string {
  switch (result.status) {
    case "ok":
      return result.data.slug;
    case "not_found":
      return "Bulunamadi";
    case "error":
      return result.message;
  }
}

switch eksik case birakirsa derleyici uyarır — any ile bu koruma gider.

Island’lar ve props sozlesmesi

Astro’da React/Svelte island props’lari JSON-serializable olmalidir. Tip tarafinda bunu bilinçli kisitlayın:

export type TocProps = {
  headings: { depth: number; slug: string; text: string }[];
  activeSlug?: string;
};

Fonksiyon, class, Date nesnesini props olarak gecirmeye calismayin; sinirda serilestirilebilir DTO kullanin. Bu kural, Python’a JSON gonderirken de ayni kafadir.

any, as, ve “sadece bu seferlik”

Olceklenebilir mimarinin dusmani sessiz kacislardir:

  • as unknown as T — alarm zili
  • // @ts-expect-error gerekceli ve gecici olmali
  • Record<string, any> yerine unknown + type guard

Type guard ornegi:

function isPublishState(x: unknown): x is PublishState {
  return x === "draft" || x === "review" || x === "published";
}

Harici API cevabini dogrudan guvenmeyin; once unknown, sonra daralt.

Python interop zihin modeli

ROS 2 / telemetri tarafinda Python; dashboard veya site tarafinda TypeScript. Ortak nokta bellek modeli degil, mesaj kontratı:

  1. Semayi tek kaynakta tutun (JSON Schema, OpenAPI, veya protobuf).
  2. TS tiplerini semadan uretin (veya semayi tipten); elle cift bakim yapmayin.
  3. Python’da pydantic / msgspec ile ayni alan adlari ve birimleri dogrulayın.
  4. Birimleri tipe yazın: speed_mps, heading_rad — “speed” yetmez.
  5. Versiyonlayın: schema_version: 1 alani, eski istemcileri oldurmeden gecis saglar.

Ornek telemetri DTO (fikir seviyesi):

type UsvTelemetryV1 = {
  schema_version: 1;
  stamp_ms: number;
  lat_deg: number;
  lon_deg: number;
  sog_mps: number;
  heading_rad: number;
  battery_v: number;
};

Dashboard bu tipi parse eder; Python publisher ayni anahtarlari uretir. “TS’te any, Python’da dict” kisa vadede hiz, uzun vadede gece debug’udur.

Modül sinirlari ve katmanlar

Buyuyen Astro reposunda klasor disiplini tip kadar onemlidir:

  • content/ — Markdown + sema
  • lib/domain/ — saf tipler ve is kurallari (framework’suz)
  • lib/http/ — fetch sarmalayicilari, hata tipleri
  • components/ — gorsel; domain’i import eder, tersi olmaz

Domain’in Astro’ya veya React’e bagimli olmaması, sonra Python testleriyle ayni kurallari paylasmayi kolaylastirir (ornek: slug kurallari iki dilde ayni regex).

Test: tipin yetmedigi yer

TypeScript calisma zamani degildir. Seridestirme, timezone, floating GPS koordinati yine bozulur. Bu yuzden:

  • Sema dogrulama testleri (gecersiz frontmatter fixture)
  • Kontrat testleri (ornek JSON dosyalari CI’da hem TS hem Python ile parse)
  • UI icin kritik island’lara dar birim test

“Tipler var diye bug yok” demiyorum; tipler bug siniflarini azaltır.

Ekip icinde olcekleme

Teknofest takimlerinde frontend’i bir kisi, otonomiyi baska kisi yazar. Tip ve sema, sozel anlasmanin yerine gecer. PR checklist’ime su satirlari eklerim:

  • Yeni public fonksiyonun donus tipi any mi?
  • Harici JSON dogrudan cast mi?
  • Frontmatter semasi guncellendi mi?
  • Python DTO ile alan adlari eslestirildi mi?

Bu, “enterprise Clean Architecture” tiyatrosu degil; kucuk ekipte iletisim protokoludur.

Sık tuzaklar (kisa)

  1. Her yere utility type yigip okunamaz hale getirmek
  2. strict kapalıyken “biz TypeScript kullaniyoruz” demek
  3. Content semasi yokken elle frontmatter varsaymak
  4. Dashboard’da birimleri belgesiz birakmak
  5. Build’i yesil tutmak icin as any ile sessize almak

Kapanis

TypeScript ile olceklenebilir mimari, framework ezberinden cok sinir ve kontrat disiplinidir. Astro’da collection semalari ve dar domain tipleri ile baslayin; Python/ROS tarafiyla konusurken ayni semayi paylasin. Hiz vaadi satmiyorum: sattigim sey, gece 02:00’de “field undefined” avini azaltan bir muhendislik aliskanligidir.