TS Hızlı Baslangıç
Burada TypeScript e hızlı bir başlangıç yapacagız. Aşagıdaki bilgiler bir anlamda daha kapsamlı bir dökümasyon için ilk notlar özelliğini taşıyor.
Daha sonra bu sayfa kaldırılacak ve daha kapsamlı TS notları eklenecektir.
Kisaca TS Nedir?
Cok kisaca buyuk projelerde JS’den yapisindan kaynaklanabilecek bazi hatalarin onune gecmeyi amaclamaktadir. En onemli ozelliligi verilerin tiplerini (types) belirterek bunlara yanlis degerler atanmasinin onune gecmek ve bu hatalari daha kodu yazarken alacagimiz TS hatalari ile onlemektir.
.ts
uzantili dosya icine yazilir.
.tsx
dosyalari TS ile JSX kullaniminda kullanilir.
Peki nedir bu hatalar yukarida bahsedilen ve TS bunlarin onune nasil geiciyor? Kisa ornek ile aciklayalim.
let message = "Merhaba, dünya!";message = 42; // Bu JS'de geçerli, ancak mantıksal hata potansiyeli taşırconsole.log(message); // Çıktı: 42
let message: string = "Merhaba, dünya!";// message = 42; // TypeScript hata verir: 'number' tipi 'string' tipine atanamaz.console.log(message); // Çıktı: "Merhaba, dünya!"
Açıklama: TypeScript’te, message
değişkeninin tipi string
olarak belirlendi. Yani message
sadece metinleri (string) tutabilir. JavaScript’te ise tip belirlemesi olmadığı için bu tür bir hata çalışma anında ortaya çıkabilir.
Yukaridaki ornekte de goruldugu gibi syntax’i su sekilde:
let message: string = "Merhaba, dünya!";// degisken isminden sonra : (iki nokta ust uste) ve tipi yaziyoruz.
Temel Tipler (Basic Types)
string
number
boolean
array
tuple
enum
any
void
null
veundefined
never
Önce en yaygın kullanılan birkaç temel tipi örneklerle görelim.
String, Number ve Boolean Tipleri
let isim: string = "Özay";let yas: number = 30;let aktif: boolean = true;
Açıklama: TypeScript’te her değişkenin türünü string, number, boolean gibi belirterek, yanlış tür atanmasını engelleyebiliriz. Mesela isim değişkeni sadece bir string alabilir; farklı bir tür verilirse hata alırız.
Any kullanimi
Asagidaki ornekte gelen verinin string mi yoksa number mi oldugunu bilmiyoruz bu yuzden any kullandik.
let userAge : any;userAge = 25 //number kabul edildiuserAge = "45" //string kabul edildiconsole.log(userAge)
Union kullanimi
//Union kullanimi. gelen verinin tipinden emin degilsek kullanmak icin Any benzeri ancak burada tipleri seciyoruz. Asagidaki ornekte oldugu gibi veri ya string
ya da number
olabilir. Baska bir deger atanamaz.
let age : string | number = "25";
Literal Type kullainimi
Biraz Union kullanimina benzeriyor ancak burada type belirlemek yerine kabul edilebilecek verileri ekliyoruz. Ornegin:
let statusResult : "pending" | "approved" | "rejected";statusResult = "pending"; //kabul edildistatusResult = "rejected"; //kabul edildi//statusResult = "ozay"; kabul edilmedi, cunku bu deger onayli degerlerden degil.
console.log(statusResult)
Degiskenlerde (Array) Type kullainimi
Degiskenlerde type kullanimi yukaridaki orneklere benzer ancak atanan tipin bir array icin oldugununu belirtmek icin []
koseli parantezleri ekleniyor.
Örneklere bakalim:
let myList : string[] = ["ozay", "Mete", "Yagmur"];// alternatif kullanim, koseli parantez kullanmadan.let myList2 : Array<string> = ["ozay", "Mete", "Yagmur"];
// Union kullanimini arraylerde de kullanabiliriz.let otherList : (string | number) [] = ["ozay", "Mete", 34, 345];
Type ve Interface Kullanimi
Kisaca interface ve type ile kendi tiplerimizi veya tip ozel tip gruplarimizi (types) olusturup kullanabiliyoruz.
Orneklere bakalim;
// asagida User adinda ozel bir tip grubu olusturuk ve// bu grub icinde name ve age degerlerine tip atatdik.type User = { name : string, age : number}
// burada tetUser icine bir kullanici bilgisi ekledik.//name ve age icin artik User altinda tipler belirlendigi icin//tip kontrolu saglamis olduk. Ornegin age'e string eklenirse ts hatasi alacagizlet testUser : User = { name : "Ozay", age : 45,}// veya bir array icine bu tipi atayabilirizlet arrayUser : User [] = []
console.log(testUser);
Interface ile ozel type olusturulmasinda simdilik sadece syntax olarak farktan basedecegim. Sonra type ve interface arasindaki farki extend
kullaniminda Link detayli gorecegiz.
// type kullanimina gore tek fark tip adindan sonra = koymamak.interface User { name: string, age: number,}
Optional type ?
Yukarida bahsettigimiz interface ve type kullaniminda soyle bir durum var. Eger siz ornegin User altinda name ve age degiskenlerine tip atamissaniz bunlari cagirdiginiz yerlerde sizden hem name hemde age degiskenleri istenecek. Eger bu degiskenlerden biri eksik ise ts hata verecektir.
Bunu asmak icin optional type dedigimiz bir yontem kullaniyoruz. Ornege bakalim;
type User = { name: string, age: number,}const testUser : User { name: "ozay",}// bu durumda testUser hata verecektir cunku ayrica age olmasi gerekiyor.// bu durumu asmak icin sadece degiskenden sonra soru isareti ? ekliyoruz.type User = { name: string, age?: number,}// bu durumda artik age degeri opsiyonel bir deger haline geldi.
Fonksiyonlarda kullanim
TS’nin fonksiyonlarda kullanimi cok onemli bir konu. Bu konu daha detaylica islenecek. Simdilik sadece syntax kullaniminda odaklanalim.
Basit kullanim: herbir degiskenin tipini belirlemek.
function topla(a:number, b:number) { console.log(a+b)}topla(5,5) // cikti 10 olacaktopla(5,"x") //ts hata verecek cunku b'nin tipi number olarak belirlendi.
Return icin tip belirleme: Bu ornekte a ve b degiskenine tip tanimlamasi yapiyoruz. Ancak ayrica bir de fonksiyonun geneline yani sonucunu (return) bir tip daha atiyoruz. Ornege bakalim;
function topla(a:number, b:number): number { return a + b;}const sonuc = topla(2,2)
console.log(sonuc) // cikti 4 olacak
//birden fazla return degeri de atamak mumkum ornegin;function topla(a:number, b:number): number | string { return a + b;}
Baska bir fonksiyon ornegi, burada hem funksiyona string atadik hemde array ile donen degerlere string atadik.
function test(myArray : string[]) { myArray.forEach((value)=> console.log(value))}let myArray : string[] = ["Ali", "Veli", "Deli"]
test(myArray)
Generic fonksiyon kullanimi
Cikacak degerin farkli tiplerde olmasi durumunda bunu generic fonksiyon kullanarak yapabiliyoruz.
Peki ama biz zaten Any
ile bunu yapabiliyoruz neden generic kullanmamiz gerekiyor? Cunku any ile tipi kaciriyoruz, generic ile tipi yakalama sansimiz oluyor.
Asagidaki ornekte yazdir
adinda bir fonksiyon olusturmak istiyoruz. Bu fonksiyon icindeki degeri console’a yazdiricak.
Ancak bu fonksiyon herhangi bir tip ile kullanilabilir. Bu durumda;
function yazdir<T>(array : T[]) :void { console.log(array)}
yazdir(["ali", "veli", "deli"]) // ["ali", "veli", "deli"]yazdir([true, false]) // [true, false]yazdir([1, 2]) // [1, 2]
Yukaridaki yapiyi biraz aciklayalim;
function yazdir (array : T[]) : void
burada diyorum ki sana T
tipinde bir array gelecek, nasil bir sey gelecegini bilmiyorum sadece T tipinde gelecek. (Bu T disinda baska bir harf de olabilir)
void
bana bir deger dondurme demek.
Simdi yazalim fonksiyonu;
function yazdir(array : T[]) :void { console.log(array)}
Bunu bu sekilde yazdigimizda T
ile ilgili bir hata aliyoruz. Diyor ki bana T verdin ancak ben bunun ne oldugunu bilmiyorum.
Bu sorunu asmak icin bu fonksiyonun bir “Generic” fonksiyon oldugunu belirtmemiz gerekiyor. Bunu da fonksiyon isminden hemen sonra <T>
ekleyerek cozuyoruz.
Yani:
function yazdir<T>(array : T[]) :void { console.log(array)}
// <T> yerine herhangi bir harf veya kelime kullanabilriz;function yazdir<Test>(array : Test[]) :void { console.log(array)}
Kullanimi daha iyi anlamak icin bir ornek daha yapalim;
interface GenericType<T> { name: string, age: number, salary: T[] // salary generic olmali cunku ne gelecegini bilmiyoruz}
const obj1 : GenericType<string> = { name: "Ali", age: 25, salary: ["1000", "2000", "3000"]}
const obj2 : GenericType<number> = { name: "Veli", age: 25, salary: [1000, 2000, 3000]}
Aciklama: Yukaridaki ornekte salary
belirsiz yani bize number
veya string
olarak gelebilir.
Bizde interface
kullanarak GenericType
adinda kendi type grubumuzu olusturuyouruz ve salary
kismini generic olarak tanimliyoruz.
Gordugunuz gibi obj1
de string
olan degerler obj2
de number
oldu ve biz her iki durumda da salary icin bir type belirlemis olduk.
Extending Types
Tekraralanan alanlari azaltmaya yonelik bir yapidir. Tekrarlanan ve ayni alan ve tipe sahip tipleri ayri ayri yazmak yerine yazilmis olanlardan almaya (Extend etmeye) yarar.
Asagidaki ornekte Musteri
ve Kurum
datalarinin tipleri belirlenmis, dikkat ederseniz ortak alanlar var yani ìd
, olustrumaTarihi
ve olusturanKisi
alanlari ayni. Buyuk projelerde tekrarlanan bu alanlar hem kod okunurlulugunu bozar hemde kod kalitesini dusurur.
interface Musteri { id: string, olusturmaTarihi: string, olusturanKisi: string, musteriNo: string,}
interface Kurum { id: string, olusturmaTarihi: string, olusturanKisi: string, kurumNo: string,}
const musteri : Musteri = { id: "1", olusturmaTarihi: "09.06.2024", olusturanKisi: "Veli", musteriNo: "234234",}
const kurum : Kurum = { id: "14", olusturmaTarihi: "09.06.2024", olusturanKisi: "Ali", kurumNo: "234566",}
Peki boyle bir durumda ne yapacagiz?
Yukaridaki ornekten yola cikalim ve ortak alanlar icin bir OrtakAlanlar
interface’i olusturalim. Musteri
ve Kurum
interface’lerinde artik tekrar eden tipler yok.
Peki Musteri
ve Kurum
interface’lerine nasil OrtakAlanlar
daki tipleri ekleyecegiz?
Bunun icin tip adindan sonra extends
ve sonra ortak alandan alacagimiz tip adini bu ornekte OrtakAlanlar
yaziyoruz.
Boylelikle Musteri icine OrtakAlanlari dahil etmis (extend etmis) oluyoruz.
interface OrtakAlanlar { id: string, olusturmaTarihi: string, olusturanKisi: string,}
interface Musteri extends OrtakAlanlar { musteriNo: string,}
interface Kurum extends OrtakAlanlar { kurumNo: string,}
const musteri : Musteri = { id: "1", olusturmaTarihi: "09.06.2024", olusturanKisi: "Veli", musteriNo: "234234",}
const kurum : Kurum = { id: "14", olusturmaTarihi: "09.06.2024", olusturanKisi: "Ali", kurumNo: "234566",}
Partial, Required, ReadOnly, pick, omit kullanimi
Partial kullanimi;
Asagidaki ornekte user1
de User
tipini cagirdigimda hata aliyorum. Cunku user1 icinde sadece name kullandim ve diger tipleri cagirmadim.
Yukarida bahsetmistik boyle bir durumda tip icindeki degerin sonuna soru isareti koyarak age?: number
bu deger optional yapabiliyorduk.
interface User { name: string, age: number, lastname: string, idno: number,}
const user1 : User = { name: "Veli",}
Peki ama User tipindeki tum elemanlara ? isareti eklemek yerine baska bir cozum var mi? Evet Partial kullanmak;
interface User { name: string, age: number, lastname: string, idno: number,}
const user1 : User = { const user1 : Partial<User> = { name: "Veli",}
Required kullanimi;
Required ise Partial’in tam tersini yapar. Yani soru isareti ile optional yapilmis tum tipleri zorunlu hale getirir. Asagidaki ornegi inceleyelim;
interface User { name?: string, age?: number, lastname?: string, idno?: number,}
// Required kullanarak tum User tiplerini eklemeyi zorunlu hale getiriyoruz.// Optional ozelligini kaldirmis oluyoruz.const user1 : Required<User> = { name: "Veli", age: 23, lastname: "Metin", idno: 234234,}
Readonly kullanimi;
Bir veriyi sadece okunabilir hale getirir. Data tekrar degistirilemez.
interface User { name?: string, age?: number, lastname?: string, idno?: number,}
const user1 : Readonly<User> = { name: "Veli",}
// user1.name = "Ali"// artik name datasini degistirmek mumkun degil
console.log(user1.name);
Pick ve Omit kullanimi;
Pick sadece belirttigimiz degiskeni almak icin kullanilir Omit ise tam tersini yapar ve belirttigimiz tipin disindakileri alir.
interface User { name: string, age: number, lastname: string, idno: number,}
// Pick sadece name aldik ve option olmamasina karsin yinede hata almadikconst user1 : Pick<User, "name"> = { name: "Veli",}
interface User { name: string, age: number, lastname: string, idno: number,}
// Omit ile User'dan name disindakileri alabiliriz name artik tanimsizconst user1 : Omit<User, "name"> = { // name: "Veli", ts name adinda bir tip bulamiyor age: 23, lastname: "Veli", idno: 12312,}