Sitemap

Typescript’in Sözdizimi

20 min readMar 30, 2025

Başka bir programlama dilini bilenler için, hızlı ve özetlenmiş TypeScript sözdizimi notlarıdır.

Typescript

TypeScript, JavaScript’in sözdizimsel bir üst kümesidir ve statik tip desteği ekleyerek daha güvenilir bir kod yazımına olanak tanır. Başka bir deyişle, TypeScript, JavaScript’in üzerine ek sözdizimi getirerek geliştiricilere, tipleri açıkça belirtme imkânı sunar.

JavaScript, zayıf tiplendirilen bir dildir, yani değişkenlerin veya fonksiyon parametrelerinin hangi tipde veri taşıdığını anlamak zor olabilir. JavaScript’te değişkenler ve fonksiyon parametreleri herhangi bir tip bilgisi içermez. Bu yüzden geliştiriciler, kodun nasıl çalıştığını anlamak için dokümantasyona bakmak ya da doğrudan kodu incelemek zorunda kalır. TypeScript ise kod içinde kullanılan verilerin tiplerini belirleme imkânı tanır ve tip uyumsuzluklarını hata olarak bildirir. Örneğin, yalnızca sayı kabul eden bir fonksiyona yanlışlıkla bir metin yani dizge (string) gönderildiğinde TypeScript bunu bir hata olarak görür ve bildirir. JavaScript ise bu tip hataları algılayamaz ve hata vereceği halde çalışmaya başlar.

TypeScript, derleme zamanı (compile-time) tip denetimi yapar. Yani, kod çalıştırılmadan önce tiplerin doğru olup olmadığı kontrol edilir. Bu, çalışma zamanında karşılaşılabilecek birçok hatanın önceden tespit edilmesini sağlar. TypeScript’i kullanmanın en yaygın yolu, resmi TypeScript derleyicisini kullanarak yazılan kodu JavaScript’e dönüştürmektir. Böylece TypeScript’in sağladığı tüm avantajlardan yararlanılırken, çıktı olarak standart JavaScript kodu elde edilebilir.

1. TypeScript Derleyicisi

TypeScript, bir derleyici kullanılarak JavaScript’e dönüştürülür. Bu sayede, TypeScript her yerde çalışabilir çünkü JavaScript’in çalıştığı her ortamda TypeScript de çalıştırılabilir olmuş olur.

Derleyicinin Yüklenmesi

TypeScript’in resmi derleyicisi npm aracılığıyla yüklenebilir. Yüklemek için npm projenizde şu komutu çalıştırın:

npm install typescript --save-dev

Bu işlem tamamlandığında, derleyici node_modules dizinine yüklenir ve şu komutla çalıştırılabilir. Bu komut, TypeScript derleyicisinin sürümünü ve genel komutları listeler.

2. Derleyicinin Konfigüre Edilmesi

Varsayılan olarak, TypeScript derleyicisi boş bir projede çalıştırıldığında bir yardım mesajı görüntüler. Derleyici, bir tsconfig.json dosyası kullanılarak yapılandırılabilir.

Aşağıdaki komut, önerilen ayarlarla bir tsconfig.json dosyası oluşturur:

npx tsc --init

Bu işlem sonucunda oluşturulan tsconfig.json dosyasında aşağıdaki temel ayarlar bulunur:

{
"target": "es2016",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}

Ayrıca, tsconfig.json içine ekleyebileceğiniz ekstra seçenekler de mevcuttur:

{
"include": ["src"],
"compilerOptions": {
"outDir": "./build"
}
}

Bu yapılandırma, src/ dizinindeki TypeScript dosyalarını build/ dizinine JavaScript olarak derleyecektir.

  • “target”: “esnext” → En yeni JavaScript özelliklerini kullanır.
  • “allowJs”: true → JavaScript dosyalarını (.js) derlemeye izin verir.
  • “skipLibCheck”: true → Dış kütüphanelerin (.d.ts dosyaları) tip denetimini atlar.
  • “esModuleInterop”: true → CommonJS ve ES modüllerini birlikte çalıştırır.
  • “strict”: true → Sıkı tip denetimi kurallarını etkinleştirir.
  • “forceConsistentCasingInFileNames”: true → Dosya adlarında büyük/küçük harf tutarlılığını zorunlu kılar.
  • “noFallthroughCasesInSwitch”: trueswitch ifadelerinde break unutulmasını önler.
  • “module”: “esnext” → En yeni ES modül sistemini kullanır.
  • “moduleResolution”: “node” → Modül çözümleme sistemini Node.js gibi yapar.
  • “resolveJsonModule”: true → JSON dosyalarının doğrudan içe aktarılmasını sağlar.
  • “isolatedModules”: true → Her dosyanın bağımsız derlenmesini zorunlu kılar.
  • “jsx”: “react-jsx” → React JSX kodunu en iyi şekilde işler.
  • “baseUrl”: “./src” → Modül yollarını ./src klasörü üzerinden çözümler.
  • “include”: [“src”] → Sadece src klasöründeki dosyaları TypeScript derlemesine dahil eder.

3. Basit Tipler

TypeScript, basit tipleri (ilkelleri) destekler.

TypeScript’te ve JavaScript’te üç ana ilkel tip vardır:

  • boolean: true veya false değerleri.
  • number (sayı): tam sayılar ve ondalıklı sayılar.
  • string (dizge): "TypeScript Rocks" gibi metin değerleri.

Daha yeni JavaScript ve TypeScript sürümlerinde kullanılan iki daha az yaygın ilkel de vardır:

  • bigint (büyük tam sayı): Tam sayılar ve ondalıklı sayılar içindir, ancak number tipinden daha büyük negatif ve pozitif sayılara izin verir.
  • symbol: Global olarak benzersiz bir tanımlayıcı oluşturmak için kullanılır.

Tip Ataması (Type Assignment)

Bir değişken oluştururken, TypeScript’in tip ataması yapmasının iki ana yolu vardır:

  1. Açık (Explicit)
  2. Örtük (Implicit)

Aşağıdaki her iki örnekte de firstName değişkeni string tipindedir.

Açık Tip Ataması (Explicit Type Assignment)

Açık bir şekilde tipi yazarak atama yapmak:

let firstName: string = "Dylan";

Açık tip atamaları, kodun daha okunaklı ve daha kasıtlı olmasını sağlar.

Örtük Tip Ataması (Implicit Type Assignment)

TypeScript, atanan değere göre tipi “tahmin eder”:

let firstName = "Dylan";

Not: TypeScript’in bir değerin tipini “tahmin etmesine” infer denir.

Örtük atamalar, TypeScript’in değeri çıkarsamasını zorunlu kılar. Örtük tip atamaları test aşaması dışında tercih edilmemelidir.

Tip Atama Hataları (Error in Type Assignment)

Eğer veri tipleri uyuşmazsa, TypeScript bir hata fırlatır.

let firstName: string = "Dylan"; // tipi string
firstName = 33; // farklı bir tip ile yeniden atama girişimi

Örtük tip ataması yapıldığında da aynı hata oluşur:

let firstName = "Dylan"; // string olarak çıkarsandı
firstName = 33; // farklı bir tip ile yeniden atama girişimi

JavaScript, tipler uyuşmasa bile hata vermez, ancak TypeScript hata verir.

Tip Çıkarsayamama (Unable to Infer)

TypeScript her zaman bir değişkenin tipini doğru bir şekilde çıkarsayamayabilir. Böyle durumlarda, tipi any olarak belirler ve tip kontrolü devre dışı kalır.

// JSON.parse ne tip bir veri döndüreceğini bilmediğinden "any" olabilir...
const json = JSON.parse("55");
// Çoğu kişi json'un bir nesne olmasını bekler, ancak bu örnekte bir string veya sayı olabilir.
console.log(typeof json);

Bu davranış, TypeScript’in proje yapılandırma dosyası tsconfig.json içinde noImplicitAny seçeneği etkinleştirilerek devre dışı bırakılabilir.

İlkel Tiplerde Büyük Harf Kullanımı

Bazı ilkel tipleri büyük harfle yazılmış şekilde görebilirsiniz:

boolean !== Boolean

Küçük harfle yazılmış tipler daha ilkeldir, büyük harfle yazılan karşılıkları özel durumlar içindir.

4. Özel Tipler

TypeScript, belirli bir veri tipine atıfta bulunmayan özel tiplere de sahiptir.

any

any, tip denetimini devre dışı bırakan ve tüm tiplerin kullanılmasına izin veren bir tiptir.

Aşağıdaki örnek any kullanmaz ve hata verecektir:

let u = true;
u = "string"; // Hata: 'string' tipi, 'boolean' tipine atanamaz.
Math.round(u); // Hata: 'boolean' tipi, 'number' parametresine atanamaz.

Özel any tipini kullanarak tip denetimini devre dışı bırakabiliriz:

let v: any = true;
v = "string"; // Hata yok çünkü "any" tipi olabilir.
Math.round(v); // Hata yok çünkü "any" tipi olabilir.

any, tip denetimini devre dışı bırakarak hataları önlemenin bir yolu olabilir. Ancak, TypeScript tip güvenliği sağlayamaz ve otomatik tamamlama gibi tipe bağlı araçlar çalışmaz. Bu nedenle, mümkün olan her durumda any kullanmaktan KAÇINILMALIDIR.

unknown

unknown, any tipine benzer ancak daha güvenlidir.

TypeScript, unknown tiplerinin kullanılmasını engeller. Aşağıdaki örnekte bu durum gösterilmektedir:

let w: unknown = 1;
w = "string"; // Hata yok
w = {
runANonExistentMethod: () => {
console.log("Düşünüyorum öyleyse varım");
}
} as { runANonExistentMethod: () => void };

// Aşağıdaki kodun hataya neden olmasını nasıl engelleriz?
// w.runANonExistentMethod(); // Hata: Nesne 'unknown' tipinde .
if (typeof w === 'object' && w !== null) {
(w as { runANonExistentMethod: Function }).runANonExistentMethod();
}

Yukarıdaki örneği any ile olan örnekle karşılaştırın.

unknown, veri tipinin bilinmediği durumlarda en iyi seçenektir. Daha sonra belirli bir tip eklemek için type casting (tip dönüştürme) yapılması gerekir. Tip dönüştürme, "as" anahtar kelimesini kullanarak bir değişkenin belirli bir tipe sahip olduğunu belirtmektir.

never

never, tanımlandığında her zaman bir hata oluşturan bir tiptir.

let x: never = true; // Hata: 'boolean' tipi, 'never' tipine atanamaz.

never nadiren kullanılır, özellikle de tek başına. Genellikle gelişmiş jeneriklerde (generics) kullanılır.

undefined ve null

undefined ve null, JavaScript'in undefined ve null ilkel tiplerine karşılık gelen tiplerdir.

let y: undefined = undefined;
let z: null = null;

Bu tipler, genellikle tsconfig.json dosyasında strictNullChecks etkinleştirilmediği sürece pek kullanışlı değildir.

5. Diziler (Arrays)

TypeScript’in dizilerin tipini vermek için belirli bir sözdizimi bulunur.

const names: string[] = [];
names.push("Dylan"); // hata yok
// names.push(3); // Hata: 'number' tipindeki argüman, 'string' tipindeki parametreye atanamaz.

Salt Okunur (Readonly)

readonly anahtar kelimesi, dizilerin değiştirilmesini önleyebilir.

const names: readonly string[] = ["Dylan"];
names.push("Jack"); // Hata: 'readonly string[]' tipinde 'push' özelliği bulunmamaktadır.
// readonly değiştiricisini kaldırmayı deneyin ve çalışıp çalışmadığını görün.

Tip Çıkarımı (Type Inference)

TypeScript, bir dizinin içeriğine bakarak tipini çıkarabilir.

const numbers = [1, 2, 3]; // number[] tipi olarak çıkarılır
numbers.push(4); // hata yok
// aşağıdaki satırı yoruma alın ve başarılı atamayı görün
numbers.push("2"); // Hata: 'string' tipindeki argüman, 'number' tipindeki parametreye atanamaz.
let head: number = numbers[0]; // hata yok

6. Demetler (Tuples)

Bir demet, her dizini için önceden tanımlanmış uzunluk ve tiplere sahip tip tanımlı bir dizidir. Demetler harikadır çünkü dizideki her öğenin belirli bir tipte olduğunu garanti ederler. Bir demet tanımlamak için, dizideki her öğenin tipini belirtmemiz gerekir.

// Demetimizi tanımlıyoruz
let ourTuple: [number, boolean, string];
// Doğru şekilde başlatma
ourTuple = [5, false, 'Kodlamanın tillahı buradaydı'];

Gördüğünüz gibi, bir number (sayı), boolean (mantıksal değer) ve bir string (metin) bulunuyor. Ancak öğeleri yanlış sırada ayarlamaya çalışırsak ne olur?

// Demetimizi tanımlıyoruz
let ourTuple: [number, boolean, string];
// Hatalı başlatma, hata verecektir
ourTuple = [false, 'Kodlamanın tillahı hata yaptı', 5];

Görünüşe göre bir boolean, string ve number var, ancak demetteki sıra önemlidir ve bu nedenle hata alırız.

Salt Okunur Tuple

İyi bir alışkanlık olarak, demetinizi readonly (salt okunur) yapabilirsiniz. Demetler yalnızca başlangıç değerleri için güçlü bir şekilde tanımlanmış tiplere sahiptir:

// Demetimizi tanımlıyoruz
let ourTuple: [number, boolean, string];
// Doğru şekilde başlatıyoruz
ourTuple = [5, false, 'Coding God buradaydı'];
// Demetimizin 3. dizininden sonra tip güvenliği yoktur
ourTuple.push('Yanlış ve yeni bir değer');
console.log(ourTuple);

Gördüğünüz gibi, demet yalnızca başlangıç değerleri için tip güvenliğine sahiptir. Bunu önlemek için salt okunurluğu kullanabiliriz.

// Salt okunur bir demet tanımlıyoruz
const ourReadonlyTuple: readonly [number, boolean, string] = [5, true, 'Gerçek Coding God'];
// Salt okunur olduğu için hata verecektir
ourReadonlyTuple.push('Coding God bir gün izin aldı');

İsimlendirilmiş Demetler

İsimlendirilmiş demetler, her dizindeki değerler için daha fazla bağlam sağlar.

const graph: [x: number, y: number] = [55.2, 41.3];

Bu şekilde, değerlerimizin neyi temsil ettiğini daha açık hale getirmiş oluruz.

Demetleri Parçalama

Demetler birer dizi olduğundan, onları parçalayabiliriz.

const graph: [number, number] = [55.2, 41.3];
const [x, y] = graph;

Bu sayede demet içindeki verilere doğrudan değişkenler üzerinden erişebiliriz.

7. Nesne Tipleri

TypeScript, nesneleri (objects) belirtmek için özel bir sözdizimine sahiptir.

const car: { type: string, model: string, year: number } = {
type: "Toyota",
model: "Corolla",
year: 2009
};

Bu tip nesne tipleri ayrı olarak da yazılabilir ve hatta tekrar kullanılabilir. Daha fazla ayrıntı için arayüzlere (interfaces) göz atabilirsiniz.

Tip Çıkarımı (Type Inference)

TypeScript, özelliklerin değerlerine dayanarak tiplerini çıkarabilir.

const car = {
type: "Toyota",
};
car.type = "Ford"; // hata yok
car.type = 2; // Hata: 'number' tipi 'string' tipine atanamaz.

İsteğe Bağlı (Optional) Özellikler

İsteğe bağlı özellikler, nesne tanımında tanımlanması zorunlu olmayan özelliklerdir.

İsteğe bağlı olmayan özellik içeren bir örnek:

const car: { type: string, mileage: number } = { 
// Hata: '{ type: string; }' tipinde 'mileage' özelliği eksik, ancak '{ type: string; mileage: number; }' tipinde gerekli.
type: "Toyota",
};
car.mileage = 2000;

İsteğe bağlı özellik içeren bir örnek:

const car: { type: string, mileage?: number } = { // hata yok
type: "Toyota"
};
car.mileage = 2000;

Dizin İmzaları (Index Signatures)

Dizin imzaları, önceden tanımlanmış bir özellik listesi olmayan nesneler için kullanılabilir.

const nameAgeMap: { [index: string]: number } = {};
nameAgeMap.Jack = 25; // hata yok
nameAgeMap.Mark = "Fifty"; // Hata: 'string' tipi 'number' tipine atanamaz.

8. Enumlar

Bir enum, değişmez (değiştirilemez) değişkenlerden oluşan özel bir “sınıf”tır. Enum’lar iki tipte olabilir: dizge ve sayısal. Öncelikle sayısal enum’lardan başlayalım.

Varsayılan Sayısal Enum’lar

Varsayılan olarak, enum’lar ilk değeri 0 olarak başlatır ve sonraki değerlere 1 ekleyerek devam eder.

enum CardinalDirections {
North,
East,
South,
West
}
let currentDirection = CardinalDirections.North;
// 0 yazdırır
console.log(currentDirection);
// Hata verir çünkü 'North' geçerli bir enum değildir
currentDirection = 'North'; // Hata: "North" tipi 'CardinalDirections' tipine atanamaz.

Başlatılmış Sayısal Enum’lar

İlk sayısal enum değerini belirleyebilir ve otomatik olarak artırılmasını sağlayabilirsiniz.

enum CardinalDirections {
North = 1,
East,
South,
West
}
// 1 yazdırır
console.log(CardinalDirections.North);
// 4 yazdırır
console.log(CardinalDirections.West);

Tamamen Başlatılmış Sayısal Enum’lar

Her enum değerine kendiniz özel bir sayı atayabilirsiniz. Bu durumda değerler otomatik olarak artmaz.

enum StatusCodes {
NotFound = 404,
Success = 200,
Accepted = 202,
BadRequest = 400
}
// 404 yazdırır
console.log(StatusCodes.NotFound);
// 200 yazdırır
console.log(StatusCodes.Success);

Dizge Enum’lar

Enum’lar string değerler de içerebilir. String enum’lar genellikle daha okunaklı ve anlaşılır oldukları için sayısal enum’lara göre daha yaygındır.

enum CardinalDirections {
North = 'North',
East = "East",
South = "South",
West = "West"
};
// "North" yazdırır
console.log(CardinalDirections.North);
// "West" yazdırır
console.log(CardinalDirections.West);

Teknik olarak string ve sayısal enum değerlerini karıştırabilirsiniz, ancak bu önerilmez.

9. Alias ve Interface

TypeScript, tiplerin onları kullanan değişkenlerden ayrı olarak tanımlanmasına izin verir. Takma Adlar (Aliases) ve Arayüzler (Interfaces), tiplerin farklı değişkenler/nesneler arasında kolayca paylaşılmasını sağlar.

Tip Takma Adları (Type Aliases)

Tip takma adları, özel bir ad (takma ad) kullanarak tiplerin tanımlanmasına olanak tanır. Tip takma adları, dizge gibi ilkel tipler veya nesneler ve diziler gibi daha karmaşık tipler için kullanılabilir.

type CarYear = number
type CarType = string
type CarModel = string

type Car = {
year: CarYear,
type: CarType,
model: CarModel
}

const carYear: CarYear = 2001
const carType: CarType = "Toyota"
const carModel: CarModel = "Corolla"

const car: Car = {
year: carYear,
type: carType,
model: carModel
};

Arayüzler (Interfaces)

Arayüzler, tip takma adlarına benzer, ancak yalnızca nesne tipleri için geçerlidir.

interface Rectangle {
height: number,
width: number
}
const rectangle: Rectangle = {
height: 20,
width: 10
};

Arayüzleri Genişletme (Extending Interfaces)

Bir arayüzü genişletmek, mevcut özellikleri koruyarak yeni özellikler eklemek anlamına gelir.

interface Rectangle {
height: number,
width: number
}
interface ColoredRectangle extends Rectangle {
color: string
}
const coloredRectangle: ColoredRectangle = {
height: 20,
width: 10,
color: "red"
};

10. Union Tipleri

Birleşim (Union) tipleri, bir değerin birden fazla tipte (örneğin dizge (string) veya sayı (number) olabileceği durumlar) olabileceği durumlarda kullanılır.

Birleşim | (VEYA)

| operatörünü kullanarak, parametremizin string veya number olduğunu belirtebiliriz.

function printStatusCode(code: string | number) {
console.log(`Durum kodum: ${code}.`);
}
printStatusCode(404);
printStatusCode('404');

Birleşim Tipi Hataları

Birleşim tipleri kullanıldığında, tip hatalarından kaçınmak için değişkenin tipini bilmek gerekir.

function printStatusCode(code: string | number) {
console.log(`Durum kodum: ${code.toUpperCase()}.`);
// Hata: 'toUpperCase' özelliği 'string | number' tipinde bulunmuyor.
// 'toUpperCase' özelliği 'number' tipinde mevcut değil.
}

Bu örnekte, toUpperCase() metodunu çağırırken hata alıyoruz çünkü bu metod yalnızca string tipine aittir, ancak number tipi bu metoda erişemez.

11. Fonksiyonlar

TypeScript, fonksiyon parametrelerini ve dönüş değerlerini belirtmek için özel bir sözdizimine sahiptir.

Dönüş Tip

Fonksiyonun döndürdüğü değerin tipi açıkça tanımlanabilir.

// Buradaki `: number`, bu fonksiyonun bir sayı döndürdüğünü belirtir.
function getTime(): number {
return new Date().getTime();
}

Eğer dönüş tipi belirtilmezse, TypeScript değişkenlerin veya döndürülen ifadelerin tipine göre bunu çıkarmaya çalışacaktır.

Void Dönüş Tipi

void tipi, bir fonksiyonun herhangi bir değer döndürmediğini belirtmek için kullanılabilir.

function printHello(): void {
console.log('Hello!');
}

Parametreler

Fonksiyon parametreleri, değişken tanımlamalarına benzer bir sözdizimi ile belirtilir.

function multiply(a: number, b: number) {
return a * b;
}

Eğer bir parametrenin tipi tanımlanmazsa, TypeScript varsayılan olarak any tipini kullanır. Ancak, aşağıda gösterildiği gibi varsayılan parametreler veya tip takma adları (type alias) gibi ek tip bilgileri mevcutsa TypeScript bunları kullanır.

Opsiyonel Parametreler

Varsayılan olarak, TypeScript tüm parametrelerin gerekli olduğunu varsayar. Ancak, parametreler açıkça opsiyonel olarak işaretlenebilir.

// Buradaki `?` operatörü, `c` parametresini opsiyonel olarak işaretler.
function add(a: number, b: number, c?: number) {
return a + b + (c || 0);
}

Varsayılan Parametreler

Varsayılan değerlere sahip parametreler için, varsayılan değer tip açıklamasından sonra gelir.

function pow(value: number, exponent: number = 10) {
return value ** exponent;
}

TypeScript, varsayılan değerden de tipi çıkarabilir.

Adlandırılmış Parametreler

Adlandırılmış parametrelerin tipleri, normal parametreler ile aynı modelde belirtilir.

function divide({ dividend, divisor }: { dividend: number, divisor: number }) {
return dividend / divisor;
}

Rest Parametreleri

Rest parametreleri, normal parametreler gibi yazılır, ancak tipleri her zaman bir dizi olmalıdır çünkü rest parametreleri her zaman bir dizi içerir.

function add(a: number, b: number, ...rest: number[]) {
return a + b + rest.reduce((p, c) => p + c, 0);
}

Tip Takma Adı (Type Alias)

Fonksiyon tipleri, fonksiyonlardan ayrı olarak tip takma adlarıyla belirtilebilir. Bu tipler, ok (arrow) fonksiyonlarına benzer şekilde yazılır.

type Negate = (value: number) => number;
// Bu fonksiyonda, `value` parametresi `Negate` tipinden dolayı otomatik olarak `number` tipine atanır.
const negateFunction: Negate = (value) => value * -1;

12. Dönüşüm (Casting)

Bazen tiplerle çalışırken, bir değişkenin tipini geçersiz kılmak gerekebilir. Örneğin, bir kütüphane yanlış tipler sağladığında bu gerekli olabilir.

Casting (Tip Dönüştürme)

Casting, bir tipi geçersiz kılma işlemidir.

as Kullanarak Dönüştürme

Bir değişkeni cast etmenin (tip dönüştürmenin) en basit yolu as anahtar kelimesini kullanmaktır. Bu, verilen değişkenin tipini doğrudan değiştirir.

let x: unknown = 'hello';
console.log((x as string).length);

Ancak, casting aslında değişkenin içindeki verinin tipini değiştirmez. Örneğin, aşağıdaki kod beklediğiniz gibi çalışmayacaktır çünkü x hâlâ bir sayı tutmaktadır:

let x: unknown = 4;
console.log((x as string).length); // undefined döndürür çünkü sayılar "length" özelliğine sahip değildir

TypeScript, mantıklı görünmeyen cast işlemlerini önlemek için tip denetlemesi yapmaya devam eder. Örneğin, aşağıdaki kod bir tip hatası verecektir çünkü TypeScript, bir sayıyı doğrudan string’e çevirmeye çalışmanın mantıksız olduğunu bilir:

console.log((4 as string).length); 
// Hata: 'number' tipinin 'string' tipine dönüştürülmesi hatalı olabilir çünkü bu iki tip birbiriyle yeterince örtüşmüyor. Eğer bu kasıtlıysa, önce ifadeyi 'unknown' tipine çevirin.

Bu tür hataları aşmanın bir yolu vardır. Aşağıdaki Zorla Casting (Force Casting) bölümünde bu ele alınmaktadır.

<> ile Dönüştürme

<> kullanımı, as kullanımıyla aynıdır.

let x: unknown = 'hello';
console.log((<string>x).length);

Bu tür casting TSX dosyalarında (örneğin, React ile çalışırken) çalışmaz ancak onun dışında hiçbir fark bulunmaz.

Zorla Dönüştürme (Force Casting)

TypeScript’in casting işlemi sırasında hata vermesini önlemek için önce unknown tipine, ardından hedef tipe çevirme yapılabilir.

let x = 'hello';
console.log(((x as unknown) as number).length);
// x aslında bir sayı olmadığı için bu kod undefined döndürecektir

13. Sınıflar

TypeScript, JavaScript sınıflarına tipler ve görünürlük belirleyicileri ekler.

Üyeler: Tipler

Bir sınıfın üyeleri (özellikler ve metotlar), değişkenlere benzer şekilde tip açıklamaları kullanılarak tanımlanır.

class Person {
name: string;
}
const person = new Person();
person.name = "Jane";

Üyeler: Görünürlük

Sınıf üyelerine, görünürlüğü etkileyen özel belirleyiciler atanabilir.

TypeScript’te üç ana görünürlük belirleyicisi vardır:

  • public: Sınıf üyesine her yerden erişime izin verir. Varsayılan belirleyicidir.
  • private: Sınıf üyesine yalnızca sınıfın içinden erişime izin verir.
  • protected: Sınıf üyesine yalnızca kendisinden ve onu miras alan sınıflardan erişime izin verir (aşağıdaki miras bölümünde ele alınmaktadır).
class Person {
private name: string;
public constructor(name: string) {
this.name = name;
}
public getName(): string {
return this.name;
}
}

const person = new Person("Jane");
console.log(person.getName()); // person.name sınıfın dışından erişilemez çünkü private

Bir sınıf içindeki this anahtar kelimesi genellikle sınıfın örneğini ifade eder.

Parametre Özellikleri

TypeScript, parametreye bir görünürlük belirleyicisi ekleyerek, sınıf üyelerini yapıcı metodunda (constructor) tanımlamak için kullanışlı bir yol sağlar.

class Person {
// name bir private üye değişkenidir
public constructor(private name: string) {}
public getName(): string {
return this.name;
}
}

const person = new Person("Jane");
console.log(person.getName());

Readonly (Salt Okunur)

Dizilerde olduğu gibi, readonly anahtar kelimesi, sınıf üyelerinin değiştirilmesini engelleyebilir.

class Person {
private readonly name: string;
public constructor(name: string) {
// name, yalnızca burada veya yapıcı metodunda tanımlanabilir ve daha sonra değiştirilemez.
this.name = name;
}
public getName(): string {
return this.name;
}
}

const person = new Person("Jane");
console.log(person.getName());

Miras: implements

Arayüzler (interface), implements anahtar kelimesi ile bir sınıfın takip etmesi gereken tipi belirlemek için kullanılabilir.

interface Shape {
getArea: () => number;
}

class Rectangle implements Shape {
public constructor(protected readonly width: number, protected readonly height: number) {}
public getArea(): number {
return this.width * this.height;
}
}

Bir sınıf, birden fazla arayüzü implements anahtar kelimesinden sonra virgülle ayırarak uygulayabilir:

class Rectangle implements Shape, Colored {

Miras: extends

Sınıflar, extends anahtar kelimesi ile birbirini genişletebilir. Bir sınıf yalnızca bir başka sınıfı genişletebilir.

interface Shape {
getArea: () => number;
}

class Rectangle implements Shape {
public constructor(protected readonly width: number, protected readonly height: number) {}
public getArea(): number {
return this.width * this.height;
}
}

class Square extends Rectangle {
public constructor(width: number) {
super(width, width);
}
// getArea, Rectangle sınıfından miras alınır
}

Üyeleri Geçersiz Kılma (Override)

Bir sınıf başka bir sınıftan türetildiğinde, üst sınıftaki üyeleri aynı adla geçersiz kılabilir.

TypeScript’in yeni sürümleri, bunu açıkça belirtmek için override anahtar kelimesini kullanmanıza olanak tanır.

interface Shape {
getArea: () => number;
}

class Rectangle implements Shape {
// protected olarak işaretlenmesi, türetilmiş sınıfların erişmesine izin verir
public constructor(protected readonly width: number, protected readonly height: number) {}
public getArea(): number {
return this.width * this.height;
}
public toString(): string {
return `Rectangle[width=${this.width}, height=${this.height}]`;
}
}

class Square extends Rectangle {
public constructor(width: number) {
super(width, width);
}
// Bu toString, Rectangle sınıfındaki toString metodunu geçersiz kılar
public override toString(): string {
return `Square[width=${this.width}]`;
}
}

Varsayılan olarak override anahtar kelimesi isteğe bağlıdır ve yalnızca var olmayan bir metodu yanlışlıkla geçersiz kılmayı önlemeye yardımcı olur. noImplicitOverride ayarını etkinleştirerek, geçersiz kılmalarda zorunlu hale getirebilirsiniz.

Soyut Sınıflar (Abstract Classes)

Sınıflar, tüm üyeleri uygulamadan, yalnızca temel sınıf olarak kullanılabilecek şekilde yazılabilir. Bu, abstract anahtar kelimesi kullanılarak yapılır. Uygulanmamış üyeler de abstract anahtar kelimesini kullanır.

abstract class Polygon {
public abstract getArea(): number;
public toString(): string {
return `Polygon[area=${this.getArea()}]`;
}
}

class Rectangle extends Polygon {
public constructor(protected readonly width: number, protected readonly height: number) {
super();
}
public getArea(): number {
return this.width * this.height;
}
}

Soyut sınıflar doğrudan örneklendirilemez, çünkü tüm üyeleri uygulanmış değildir.

14. Temel Jenerikler

Generics, “tip değişkenleri” oluşturarak sınıflar, fonksiyonlar ve tip takma adları oluşturmayı sağlar. Böylece kullanılan tiplerin açıkça tanımlanmasına gerek kalmaz.

Generics, yeniden kullanılabilir kod yazmayı kolaylaştırır.

Fonksiyonlar

Generics ile fonksiyonlar, kullanılan ve döndürülen tipleri daha doğru bir şekilde temsil eden genel metodlar haline gelir.

function createPair<S, T>(v1: S, v2: T): [S, T] {
return [v1, v2];
}
console.log(createPair<string, number>('hello', 42)); // ['hello', 42]

TypeScript, fonksiyon parametrelerinden generics parametrelerinin tipini de çıkarabilir.

Sınıflar

Generics, Map gibi genelleştirilmiş sınıflar oluşturmak için de kullanılabilir.

class NamedValue<T> {
private _value: T | undefined;
constructor(private name: string) {}
public setValue(value: T) {
this._value = value;
}
public getValue(): T | undefined {
return this._value;
}
public toString(): string {
return `${this.name}: ${this._value}`;
}
}

let value = new NamedValue<number>('myNumber');
value.setValue(10);
console.log(value.toString()); // myNumber: 10

TypeScript, generics parametresinin tipini, eğer bir constructor parametresinde kullanılmışsa çıkarabilir.

Tip Takma Adları (Type Aliases)

Generics, tip takma adlarında kullanılarak daha yeniden kullanılabilir tipler oluşturulabilir.

type Wrapped<T> = { value: T };
const wrappedValue: Wrapped<number> = { value: 10 };

Bu yapı, aşağıdaki sözdizimi ile arabirimlerde (interfaces) de kullanılabilir:

interface Wrapped<T> { ... }

Varsayılan Değer

Generics, eğer başka bir değer belirtilmezse veya çıkarılmazsa uygulanacak varsayılan değerlere sahip olabilir.

class NamedValue<T = string> {
private _value: T | undefined;
constructor(private name: string) {}
public setValue(value: T) {
this._value = value;
}
public getValue(): T | undefined {
return this._value;
}
public toString(): string {
return `${this.name}: ${this._value}`;
}
}

let value = new NamedValue('myNumber');
value.setValue('myValue');
console.log(value.toString()); // myNumber: myValue

Kısıtlamalar (Extends)

Generics’e kısıtlamalar ekleyerek hangi tiplerin kullanılabileceğini sınırlandırmak mümkündür. Bu sayede generics tipi kullanılırken daha belirli bir tipe güvenilebilir.

function createLoggedPair<S extends string | number, T extends string | number>(v1: S, v2: T): [S, T] {
console.log(`creating pair: v1='${v1}', v2='${v2}'`);
return [v1, v2];
}

Bu yapı, varsayılan bir değer ile birleştirilebilir.

15. Yardımcı Tipler

TypeScript, yaygın tip manipülasyonlarına yardımcı olabilecek birçok tiple birlikte gelir. Bunlar genellikle yardımcı tipler olarak adlandırılır.

En popüler yardımcı tipleri öğrenelim.

Partial

Partial, bir nesnedeki tüm özellikleri isteğe bağlı hale getirir.

interface Point {
x: number;
y: number;
}

let pointPart: Partial<Point> = {}; // `Partial`, x ve y'nin isteğe bağlı olmasını sağlar
pointPart.x = 10;

Required

Required, bir nesnedeki tüm özellikleri zorunlu hale getirir.

interface Car {
make: string;
model: string;
mileage?: number;
}

let myCar: Required<Car> = {
make: 'Ford',
model: 'Focus',
mileage: 12000 // `Required`, mileage özelliğini zorunlu hale getirir
};

Record

Record, belirli bir anahtar tipi ve değer tipi ile bir nesne tipi tanımlamak için kullanılan bir kısayoldur.

const nameAgeMap: Record<string, number> = {
'Alice': 21,
'Bob': 25
};

Record<string, number> şu anlama gelir: { [key: string]: number }

Omit

Omit, bir nesne tipinden belirli anahtarları kaldırır.

interface Person {
name: string;
age: number;
location?: string;
}

const bob: Omit<Person, 'age' | 'location'> = {
name: 'Bob'
// `Omit`, age ve location özelliklerini kaldırdı, bu yüzden burada tanımlanamazlar
};

Pick

Pick, bir nesne tipinden yalnızca belirtilen anahtarları alır.

interface Person {
name: string;
age: number;
location?: string;
}

const bob: Pick<Person, 'name'> = {
name: 'Bob'
// `Pick`, sadece name özelliğini bıraktı, bu yüzden age ve location burada kullanılamaz
};

Exclude

Exclude, bir birleşim tipinden belirli tipleri kaldırır.

type Primitive = string | number | boolean;
const value: Exclude<Primitive, string> = true;
// `Exclude`, string tipini kaldırdığı için burada string kullanılamaz.

ReturnType

ReturnType, bir fonksiyon tipinin dönüş tipini çıkarır.

type PointGenerator = () => { x: number; y: number; };
const point: ReturnType<PointGenerator> = {
x: 10,
y: 20
};

Parameters

Parameters, bir fonksiyon tipinin parametre tiplerini bir dizi olarak çıkarır.

type PointPrinter = (p: { x: number; y: number; }) => void;
const point: Parameters<PointPrinter>[0] = {
x: 10,
y: 20
};

Readonly

Readonly, bir nesne tipindeki tüm özellikleri salt okunur hale getirir, yani bir kere değer atandıktan sonra değiştirilemezler.

Dikkat: TypeScript bunu derleme zamanı engeller, ancak sonuçta kod JavaScript’e dönüştüğünden, teoride readonly özelliği hala geçersiz kılınabilir.

interface Person {
name: string;
age: number;
}

const person: Readonly<Person> = {
name: "Dylan",
age: 35,
};

person.name = 'Barkın'; // Hata: 'name' özelliğine atama yapılamaz çünkü salt okunurdur.

16. Keyof

“keyof, TypeScript’te bir nesne tipinden anahtar tipini çıkarmak için kullanılan bir anahtar kelimedir.

keyof ile Açık Anahtarlar

Bir nesne tipi üzerinde açık anahtarlarla kullanıldığında, keyof bu anahtarlarla bir birleşim (union) tipi oluşturur.

interface Person {
name: string;
age: number;
}

// `keyof Person` burada "name" ve "age" birleşim tipini oluşturur, diğer string değerler kabul edilmez.
function printPersonProperty(person: Person, property: keyof Person) {
console.log(`Kişi özelliği ${property} yazdırılıyor: "${person[property]}"`);
}
let person = {
name: "Max",
age: 27
};
printPersonProperty(person, "name"); // Kişi özelliği name yazdırılıyor: "Max"

keyof ile Dizin İmzaları

keyof, dizin imzaları ile kullanılarak dizin tipini de çıkarabilir.

type StringMap = { [key: string]: unknown };

// `keyof StringMap` burada `string` olarak çözülür.
function createStringPair(property: keyof StringMap, value: string): StringMap {
return { [property]: value };
}

17. Null

TypeScript, null veya undefined değerlerle başa çıkmak için güçlü bir sisteme sahiptir.

Varsayılan olarak, null ve undefined yönetimi devre dışıdır ve strictNullChecks ayarı true olarak ayarlanarak etkinleştirilebilir.

Bu sayfanın geri kalanı, strictNullChecks etkinleştirildiği zaman kullanılabilir.

Tipler

null ve undefined, diğer tipler (örneğin string) gibi kullanılabilen ilkel (primitive) tiplerdir.

let value: string | undefined | null = null;
value = 'hello';
value = undefined;

strictNullChecks etkinleştirildiğinde, TypeScript, undefined açıkça tip tanımına eklenmediği sürece değerlerin atanmasını gerektirir.

Opsiyonel Zincirleme (Optional Chaining)

Opsiyonel Zincirleme, TypeScript’in null yönetimiyle iyi çalışan bir JavaScript özelliğidir. Bir nesnedeki var olup olmadığı bilinmeyen özelliklere daha kompakt bir sözdizimi ile erişilmesini sağlar. Özelliklere erişirken ?. operatörü ile kullanılabilir.

interface House {
sqft: number;
yard?: {
sqft: number;
};
}

function printYardSize(house: House) {
const yardSize = house.yard?.sqft;
if (yardSize === undefined) {
console.log('No yard');
} else {
console.log(`Yard is ${yardSize} sqft`);
}
}
let home: House = {
sqft: 500
};
printYardSize(home); // 'No yard' yazdırır

Nullish Birleştirme (Nullish Coalescence)

Nullish Birleştirme, TypeScript’in null yönetimiyle iyi çalışan bir başka JavaScript özelliğidir. Bu özellik, özellikle null veya undefined değerlerle çalışırken, bir yedek (fallback) ifade yazılmasına olanak tanır. Ancak diğer falsy (false benzeri) değerler (örneğin 0 veya boş string) hâlâ geçerli sayılır. ?? operatörü ile kullanılabilir.

function printMileage(mileage: number | null | undefined) {
console.log(`Mileage: ${mileage ?? 'Not Available'}`);
}

printMileage(null); // 'Mileage: Not Available' yazdırır
printMileage(0); // 'Mileage: 0' yazdırır

Null İddiası (Null Assertion)

TypeScript’in çıkarım sistemi her zaman mükemmel değildir; bazı durumlarda bir değerin null veya undefined olma olasılığını göz ardı etmek mantıklı olabilir. Bunu yapmanın en kolay yollarından biri tip dönüşümü (casting) kullanmaktır, ancak TypeScript ayrıca ! operatörünü kısa yol olarak sağlar.

function getValue(): string | undefined {
return 'hello';
}
let value = getValue();
console.log('value length: ' + value!.length);

Tıpkı tip dönüşümünde olduğu gibi, bu yöntem de güvensiz olabilir ve dikkatle kullanılmalıdır.

Dizi Sınırları Yönetimi (Array Bounds Handling)

strictNullChecks etkin olsa bile, varsayılan olarak TypeScript, bir diziden yapılan erişimlerin hiçbir zaman undefined döndürmeyeceğini varsayar (tabii ki, dizinin tipi açıkça undefined içermediği sürece).

Bu varsayımı değiştirmek için noUncheckedIndexedAccess yapılandırması kullanılabilir.

let array: number[] = [1, 2, 3];
let value = array[0]; // `noUncheckedIndexedAccess` etkinleştirildiğinde, bu değer `number | undefined` tipine sahip olur.

18. Kesinlikle Tiplendirilmiş (Definetely Typed)

NPM paketleri, geniş JavaScript ekosisteminde her zaman tiplere sahip olmayabilir. Bazen projeler artık bakım görmüyor, bazen de geliştiriciler TypeScript kullanmakla ilgilenmiyor, buna katılmıyor ya da buna ayıracak vakitleri olmuyor.

TypeScript’te Tip Tanımı Olmayan NPM Paketlerini Kullanmak

Tip tanımları olmayan NPM paketlerini TypeScript ile kullanmak, tip eksikliği nedeniyle güvenli olmayacaktır.

TypeScript geliştiricilerinin bu tip paketleri kullanmasına yardımcı olmak için Definitely Typed adlı, topluluk tarafından sürdürülen bir proje bulunmaktadır.

Definitely Typed, tip tanımları bulunmayan NPM paketleri için merkezi bir TypeScript tanım deposu sağlayan bir projedir.

Örnek: TypeScript İçin Tanım Paketi Yüklemek

npm install --save-dev @types/jquery

Bildirim paketini yükledikten sonra genellikle başka bir adım atmanıza gerek kalmaz. TypeScript, paketi kullanırken tipleri otomatik olarak algılar.

Visual Studio Code gibi editörler, eksik tipler tespit ettiğinde bu tür paketleri yüklemeyi sıklıkla önerir.

19. TS5 Güncellemeleri

TypeScript, Microsoft tarafından aktif olarak geliştirilmekte ve güncellenmektedir. 5.x sürümünde birçok yardımcı araç ve kullanım kalitesi güncellemeleri yapıldı. Bu bölüm, daha katı ve esnek tip güvenliği sağlamak için en popüler güncellemeleri kapsar. Hatırlatma: Bu özellikler yalnızca 5.x ve üstü sürümlerde mevcut olacaktır.

Şablon Literal Tipleri

Şablon Literal Tipleri, şablon dizgelerini kullanarak daha hassas tipler oluşturmamıza olanak tanır. Derleme aşamasında dizgelerin gerçek değerlerine bağlı özel tipler tanımlayabiliriz.

type Color = "red" | "green" | "blue";
type HexColor<T extends Color> = `#${string}`;
// Kullanım:
let myColor: HexColor<"blue"> = "#0000FF";

Dizin İmzası Etiketleri

Dizin İmzası Etiketleri, dizin imzalarına hesaplanmış özellik adları kullanarak etiket eklememizi sağlar. Bu, dinamik nesnelerle çalışırken daha açıklayıcı tip bilgisi sağlamaya yardımcı olur.

type DynamicObject = { [key: string as `dynamic_${string}`]: string };
// Kullanım:
let obj: DynamicObject = { dynamic_key: "value" };

Ayrıca, 5.x sürümü artık yerel JavaScript özel alanlarını (private fields) desteklemektedir. TypeScript’in private anahtar kelimesi de Sınıflar bölümünde tartışıldığı gibi çalışmaya devam etmektedir.

Kaynak

W3Schools, (2025), Typescript:

[https://www.w3schools.com/typescript/]

--

--

Cahit Barkin Ozer
Cahit Barkin Ozer

Written by Cahit Barkin Ozer

Üretken YZ başta olmak üzere teknoloji alanındaki yenilikleri öğrenip sizlerle paylaşıyorum. Youtube Kanalım: https://www.youtube.com/@cbarkinozer

No responses yet