TypeScript Type Challenges ile Tip Sistemini Keşfetmek

Yunus Emre Güzel
6 Ocak 202510 dkTypeScript
TypeScript Type Challenges ile Tip Sistemini Keşfetmek

TypeScript Type Challenges ile Tip Sistemini Keşfetmek

TypeScript'in tip sistemi, JavaScript ekosisteminde güvenli ve ölçeklenebilir uygulamalar geliştirmek için güçlü bir araçtır. Bu yazıda, TypeScript'in gelişmiş tip özelliklerini inceleyecek ve type challenges örnekleri üzerinden tip manipülasyonu tekniklerini öğreneceğiz.

Temel Tip Kavramları ve Generic Types

TypeScript'te tip güvenliği sağlamanın temelinde generic tipler yatar. Generic tipler, farklı veri tipleriyle çalışabilen esnek ve yeniden kullanılabilir kod yazmanıza olanak tanır.

// Generic bir fonksiyon örneği
function identity<T>(arg: T): T {
  return arg;
}

// Generic bir interface örneği
interface Box<T> {
  value: T;
  setValue: (newValue: T) => void;
}

// Kullanım örneği
const numberBox: Box<number> = {
  value: 42,
  setValue: (newValue) => {
    numberBox.value = newValue;
  }
};

Conditional Types ve Type Inference

Conditional types, tip sisteminde koşullu mantık uygulamanıza olanak tanır. Bu özellik, tipleri dinamik olarak belirlemek için kullanılır.

// Bir tipin string olup olmadığını kontrol eden conditional type
type IsString<T> = T extends string ? true : false;

// Kullanım örnekleri
type Result1 = IsString<"hello">; // true
type Result2 = IsString<42>; // false

// Daha karmaşık bir örnek: Bir array tipinin elemanlarını çıkaran type
type UnpackArray<T> = T extends Array<infer U> ? U : T;

type NumberArray = number[];
type ExtractedType = UnpackArray<NumberArray>; // number

Utility Types ve Type Manipulation

TypeScript, tip manipülasyonu için birçok yerleşik utility type sunar. Bu tipler, mevcut tipleri dönüştürmek ve yeni tipler oluşturmak için kullanılır.

// Interface tanımı
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;
  createdAt: Date;
}

// Partial: Tüm özellikleri opsiyonel yapar
type PartialUser = Partial<User>;

// Pick: Belirli özellikleri seçer
type UserBasicInfo = Pick<User, "name" | "email">;

// Omit: Belirli özellikleri çıkarır
type UserWithoutDates = Omit<User, "createdAt">;

// Record: Key-value yapısı oluşturur
type UserRoles = Record<string, "admin" | "user" | "guest">;

Type Guards ve Type Narrowing

Type guards, runtime'da tip güvenliği sağlamak için kullanılan özel fonksiyonlardır. Bu fonksiyonlar, bir değerin belirli bir tipte olduğunu garanti eder.

// Custom type guard örneği
interface Car {
  brand: string;
  model: string;
  year: number;
}

interface Motorcycle {
  brand: string;
  type: string;
  cc: number;
}

// Type guard fonksiyonu
function isCar(vehicle: Car | Motorcycle): vehicle is Car {
  return "model" in vehicle && "year" in vehicle;
}

// Kullanım örneği
function processVehicle(vehicle: Car | Motorcycle) {
  if (isCar(vehicle)) {
    // Bu blokta vehicle kesinlikle Car tipinde
    console.log(`${vehicle.brand} ${vehicle.model} ${vehicle.year}`);
  } else {
    // Bu blokta vehicle kesinlikle Motorcycle tipinde
    console.log(`${vehicle.brand} ${vehicle.type} ${vehicle.cc}cc`);
  }
}

Mapped Types ve Template Literal Types

Mapped types ve template literal types, tip sisteminde meta-programlama yapmanıza olanak tanır.

// Mapped type örneği
type ReadonlyFields<T> = {
  readonly [K in keyof T]: T[K];
};

// Template literal type örneği
type CSSProperty = "margin" | "padding" | "border";
type CSSDirection = "top" | "right" | "bottom" | "left";
type CSSValue = `${CSSProperty}-${CSSDirection}`;

// Kullanım örneği
const style: Record<CSSValue, string> = {
  "margin-top": "10px",
  "padding-left": "20px",
  "border-bottom": "1px solid black",
  // ...
};

Advanced Type Challenges

İşte bazı ileri seviye tip challenge'ları ve çözümleri:

// Challenge 1: Tuple'ı tersine çeviren tip
type Reverse<T extends any[]> = T extends [...infer Rest, infer Last]
  ? [Last, ...Reverse<Rest>]
  : [];

// Test
type ReversedTuple = Reverse<[1, 2, 3, 4, 5]>; // [5, 4, 3, 2, 1]

// Challenge 2: String literal'ı capitalize eden tip
type Capitalize<S extends string> = S extends `${infer First}${infer Rest}`
  ? `${Uppercase<First>}${Rest}`
  : S;

// Test
type CapitalizedString = Capitalize<"hello">; // "Hello"

// Challenge 3: Promise'ın return tipini çıkaran tip
type UnpackPromise<T> = T extends Promise<infer U>
  ? U extends Promise<any>
    ? UnpackPromise<U>
    : U
  : T;

// Test
type PromiseType = UnpackPromise<Promise<Promise<string>>>; // string

Sonuç

TypeScript'in tip sistemi, sadece tip güvenliği sağlamakla kalmaz, aynı zamanda kodunuzu daha okunabilir ve bakımı kolay hale getirir. Type challenges ile tip sisteminin gücünü keşfederek, daha güvenli ve sağlam uygulamalar geliştirebilirsiniz.

Tip sistemini etkin kullanmak için öneriler:

  • Generic tipleri mümkün olduğunca kullanın
  • Utility type'ları tanıyın ve kullanın
  • Type guard'ları doğru yerlerde kullanın
  • Tip tanımlarınızı modüler ve yeniden kullanılabilir yapın
  • Type inference'ı akıllıca kullanın

İlgili Etiketler: #TypeScript #TypeSystem #GenericTypes #UtilityTypes #TypeGuards #TypeInference #AdvancedTypes

Kaynaklar