TypeScript'e Giriş
Yayınlanan: 2020-10-29Programladığım ilk diller C ve Java. Bu dillerde, her değişken tanımladığınızda türünü belirtmeniz gerekir. Buna başka türden bir değer atamaya çalışırsanız, derleyici şikayet eder:
// main.c int main() { int x = "two"; return 0; } > cc main.c -o main // warning: initialization makes integer from pointer without a castSorun şu ki, deneyim eksikliğimden dolayı derleyiciden aldığım şikayetlerin çoğu şifreli ve karmaşık görünüyordu. Bu yüzden, sonunda derleyiciye yaratıcılığımı sınırlayan bir araç olarak baktım, oysa gerçekte yardım etmek için orada olan bir ortak olması gerekiyordu.

Daha sonra kariyerimde JavaScript veya PHP gibi güçlü yazım gerektirmeyen bazı programlama dillerini kullanmaya başladım. Oldukça havalı olduklarını düşündüm: seçici bir derleyici ile uğraşmak zorunda kalmadan bir şeyleri hızlı bir şekilde prototiplemek son derece kolaydı.
Bildiğiniz gibi, WordPress'in temel aldığı programlama dilleri PHP ve JavaScript'tir. Bu, muhtemelen arkanızı kollayan bir derleyici olmadan eklentilerinizi ve temalarınızı kodlamaya alıştığınız anlamına gelir. Sadece siz, becerileriniz ve yaratıcılığınız. Peki, ve bunun gibi hatalar:
const user = getUser( userId ); greet( user.name ); // Uncaught TypeError: user is undefined Kodunuzdaki undefined benzeri hatalardan bıktıysanız, iş akışınıza bir derleyici eklemenin zamanı geldi. TypeScript'in ne olduğuna ve yazılımımızın kalitesini birkaç derece artırmamıza nasıl izin verdiğine bir göz atalım.
TypeScript nedir?
TypeScript, güçlü ve statik yazma eklemek amacıyla oluşturulmuş JavaScript tabanlı bir programlama dilidir. TypeScript türleri, nesnelerimizin ve değişkenlerimizin şeklini tanımlamamıza izin vererek daha iyi belgelenmiş ve daha sağlam bir kod elde etmemizi sağlar. TypeScript, yaptığımız her şeyi doğrulamaktan sorumlu olacaktır.
Tasarlandığı gibi TypeScript, JavaScript'in bir üst kümesidir. Bu, düz JavaScript ile yazılmış herhangi bir kodun tanım gereği aynı zamanda geçerli TypeScript olduğu anlamına gelir. Ancak bunun tersi doğru değildir: TypeScript'e özgü özellikler kullanırsanız, elde edilen kod, siz onu aktarana kadar geçerli JavaScript değildir.
TypeScript Nasıl Çalışır?
TypeScript'in nasıl çalıştığını anlamak için, TypeScript kodunu yazabileceğimiz ve derleyicinin bize bunun hakkında ne söylediğini görebileceğimiz küçük bir düzenleyici olan Playground'u kullanacağız.
JavaScript'in bir üst kümesi olarak TypeScript kodu yazmak son derece kolaydır. Temel olarak aşağıdaki JavaScript kodu:
let user = "David"; let age = 34; let worksAtNelio = true; console.log( user, age, worksAtNelio );ayrıca TypeScript kodudur. TypeScript Playground'a kopyalayıp yapıştırabilirsiniz ve derlendiğini göreceksiniz. Peki bu kadar özel olan ne? Elbette türleri. JavaScript'te aşağıdakileri yapabilirsiniz:
let user = "David"; let age = 34; let worksAtNelio = true; user = { name: "Ruth" }; console.log( user, age, worksAtNelio );ancak bu, TypeScript'te bir hatayı tetikleyecektir. Sadece Oyun Alanında deneyin ve aşağıdaki hatayı göreceksiniz:
Type '{ name: string; }' is not assignable to type 'string'.Peki bu ne hakkında?
TypeScript, bir değişkenin türünü otomatik olarak çıkarabilir. Bu, ona açıkça "hey, bu değişken bir dizgedir" (veya bir sayı, bir boole veya her neyse) dememize gerek olmadığı anlamına gelir; bunun yerine, kendisine ilk verilen değere bakar ve buna göre türünü çıkarır.

Örneğimizde, user değişkenini tanımladığımızda, ona "David" metin dizesini atadık, bu nedenle TypeScript, user bir dize olduğunu (ve her zaman olması gerektiğini) bilir. Sorun şu ki, biraz sonra, değeri "Ruth" dizesi olan tek bir özelliğe ( name ) sahip bir nesne atayarak user değişkenimizin türünü değiştirmeye çalışıyoruz. Açıkçası, bu nesne bir dize değil, bu nedenle TypeScript şikayet ediyor ve bize atamanın gerçekleştirilemeyeceğini söylüyor.
Bunu düzeltmenin iki olası yolu vardır:
// Option 1 let user = "David"; user = "Ruth"; // OK. // Option 2 let user = { name: "David" }; user = { name: "Ruth" };Değişkenlerimizin türlerini tanımlarken açık olalım
Ancak tür çıkarımı yalnızca bize yardımcı olmak için oradadır. İstersek, TypeScript'e bir değişkenin türünü açıkça söyleyebiliriz:
let user: string = "David"; let age: number = 34; let worksAtNelio: boolean = true; console.log( user, age, worksAtNelio );bu, TypeScript tarafından çıkarılan türlerle tam olarak aynı sonucu verir. Şimdi bu şu soruyu akla getiriyor: TypeScript türleri otomatik olarak çıkarabiliyorsa, neden bu özelliğe ihtiyacımız var?
Bir yandan, türleri açıkça belirtmek kodumuzu daha iyi belgelemeye hizmet edebilir (bu, sonraki bölümde daha da netleşecektir). Öte yandan, tür çıkarım sisteminin sınırlamalarını çözmemizi sağlar. Evet, doğru okudunuz: çıkarımın çok iyi olmadığı durumlar vardır ve TypeScript'in yapabileceği en iyi şey, “pekala, bu değişkenin tam olarak ne olması gerektiğini bilmiyorum; Sanırım her şey olabilir!"
Aşağıdaki örneği göz önünde bulundurun:
const getName = ( person ) => person.name; let david = { name: "David", age: 34 }; console.log( getName( david ) ); // Parameter 'person' implicitly has an 'any' type. Bu durumda, bir parametre alan ve bir değer döndüren bir getName işlevi tanımlıyoruz. Bu kadar basit bir fonksiyonda ne kadar çok şey varsaydığımıza dikkat edin: name adında en az bir özelliği olan bir nesne ( person ) bekliyoruz. Ancak bu işlevi arayan kişinin onu doğru şekilde kullanacağına dair hiçbir garantimiz yok. Ama yapsalar bile, bu işlevin ortaya çıkan türünün ne olduğunu hala bilmiyoruz. Elbette, bir ismin string olacağını varsayabilirsin, ama bunu sadece bir insan olduğun ve o kelimenin anlamını anladığın için biliyorsun. Ancak aşağıdaki örneklere bakın:
getName( "Hola" ); // Error getName( {} ); // Returns undefined getName( { name: "David" } ); // Returns a string getName( { name: true } ); // Returns a booleanfonksiyonu her çağırdığımızda farklı bir sonuç alıyoruz! Bu nedenle, TypeScript'in arkamızı kollamasına rağmen, hala klasik JavaScript sorunlarıyla karşılaşıyoruz: bu işlev her şeyi alabilir ve her şeyi döndürebilir.


Çözüm, tahmin ettiğiniz gibi, işlevi açıkça açıklamaktır.
Kendi türlerinizi tanımlayın
Ancak bunu yapmadan önce, başka bir TypeScript özelliği görelim: özel veri türleri. Şimdiye kadar, neredeyse tüm örneklerimiz, anlaşılması oldukça kolay olduğunu düşündüğüm string , number , boolean vb. gibi temel türleri kullandı. Ayrıca nesneler gibi daha karmaşık veri yapıları da gördük:
let david = { name: "David", age: 34 };ama TypeScript'ten anlaşıldığı gibi türüne fazla dikkat etmedik, değil mi? Tek gördüğümüz, yazım uyuşmazlığı nedeniyle geçersiz bir atama örneği:
let user = "David"; user = { name: "Ruth" }; // Type '{ name: string; }' is not assignable to type 'string'.bu bir şekilde nesnenin türünün “ {name:string;} ” olduğunu ima etti, bunu “bu, name of type string adlı bir özelliğe sahip bir nesnedir ” şeklinde okuyabilirsiniz. Nesne türleri bu şekilde tanımlanırsa, aşağıdakiler geçerli TypeScript olmalıdır:
let david: { name: string, age: number } = { name: "David", age: 34 };ve gerçekten öyle. Ama eminim ki bunun kullanışlı olmaktan başka bir şey olmadığı konusunda hemfikirsinizdir. Neyse ki TypeScript'te yeni türler oluşturabiliriz.
Genel olarak, özel bir tür temel olarak özel bir ada sahip normal bir TypeScript türüdür:
type Person = { name: string; age: number; }; let david: Person = { name: "David", age: 34 }; Havalı değil mi? Artık Kişi türüne sahip olduğumuza göre, getName işlevimize kolayca açıklama ekleyebilir ve giriş parametremizin türünü açıkça belirtebiliriz:
const getName = ( person: Person ) => person.name; Ve bu basit güncelleme TypeScript'e pek çok bilgi veriyor! Örneğin, bir Person nesnesinin name özniteliğinin de bir dize olduğunu kesin olarak bildiğinden, artık bu işlevin sonuç türünün bir dize olduğu sonucuna varabilir:
let david: Person = { name: "David", age: 34 }; let davidName = getName( david ); davidName = 2; // Type 'number' is not assignable to type 'string'.Ancak, her zaman olduğu gibi, isterseniz sonuç türüne açıkça açıklama ekleyebilirsiniz:
const getName = ( person: Person ): string => person.name;TypeScript türleriyle ilgili daha fazla şey…
Son olarak, TypeScript'te kendi türlerinizi tanımlarsanız yararlanabileceğiniz birkaç ilginç özelliği sizinle paylaşmak istedim.
Değişkenlere değer atamak söz konusu olduğunda TypeScript çok talepkardır. Belirli bir değişkenin türünü açıkça tanımladıysanız, yalnızca o türle tam olarak eşleşen değerleri atayabilirsiniz. Birkaç örnekle görelim:
type Person = { name: string; age: number; }; let david: Person = { name: "David", age: 34 }; // OK let ruth: Person = { name: "Ruth" }; // Property 'age' is missing in type '{ name: string; }' but required in type 'Person' let toni: Person = { name: "Toni", age: 35, gender: "M" }; // Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'. Object literal may only specify known properties, and 'gender' does not exist in type 'Person'. Gördüğünüz gibi, bir Kişi değişkeni yalnızca Kişi türüne tam olarak uyan nesneleri kabul eder. Bazı öznitelikler eksikse ( ruth age yok) veya türe dahil edilenlerden daha fazla öznitelik varsa ( toni gender var), TypeScript şikayet edecek ve bir tür uyuşmazlığı hatasını tetikleyecektir.
Ancak, fonksiyonları çağırmaktan bahsediyorsak, işler farklıdır! Bir işlevdeki bağımsız değişken türleri kesin bir gereklilik değildir, ancak parametrelerin uyması gereken minimum arabirimi belirtin. Biliyorum, biliyorum, bu çok soyut. Her şeyi daha net hale getireceğine inandığım aşağıdaki örneğe bir göz atalım:
type NamedObject = { name: string; }; const getName = ( obj: NamedObject ): string => obj.name; const ruth = { name: "Ruth" } getName( ruth ); // OK const david = { name: "David", age: 34 }; getName( david ); // OK const toni = { firstName: "Toni" }; getName( toni ); // Argument of type '{ firstName: string; }' is not assignable to parameter of type 'NamedObject'. Property 'name' is missing in type '{ firstName: string; }' but required in type 'NamedObject'. Gördüğünüz gibi, getName işlevini biraz daha genel bir şey olarak yeniden tanımladık: şimdi bir NamedObject nesnesi, yani name türünde string türünde bir özniteliğe sahip olması gereken bir nesne alıyor. Bu tanımı kullanarak, ruth ve david bu gereksinimlerle ne kadar mükemmel bir şekilde eşleştiğini görüyoruz (ikisinin de bir name özniteliği vardır), ancak toni name beklenilen özniteliğe sahip olmadığı için yoktur.
Çözüm
TypeScript, statik tür tanımları ekleyerek JavaScript'i genişleten bir programlama dilidir. Bu, birlikte çalıştığımız verileri tanımlarken çok daha hassas olmamızı sağlar ve daha da önemlisi, hataları daha erken tespit etmemize yardımcı olur.
TypeScript'i bir geliştirme yığınına entegre etmenin maliyeti nispeten küçüktür ve kademeli olarak yapılabilir. Tüm JavaScript kodları, tanım olarak TypeScript olduğundan, JavaScript'ten TypeScript'e geçiş otomatiktir - her seferinde bir adım tür ekleyebilir ve kodunuzu süsleyebilirsiniz.
Bu gönderiyi beğendiyseniz ve daha fazlasını öğrenmek istiyorsanız, lütfen paylaşın ve aşağıdaki yorum bölümünde bana bildirin.
King's Church International'ın Unsplash'ta Öne Çıkan Görseli.
