TypeScript’de interface kavramı, Javascript’deki, genişletilebilirliği sağlayan en esnek yapı. Normalde Javascript’de interface kavramı bildiğiniz üzere yok. Dolayısıyla type-safe bir yapı oluşturmak, doğası gereği zor. TypeScript’de ki interface’ler temel olarak bu zorluğu ortadan kaldırmak için geliştirilmiş diyebiliriz.
TypeScript’deki interface, temelinde bir tip tanımından başka birşey değildir. class ve function‘lar nesnelerin davranışlarını tanımlarken, interface‘ler nesnelerin tiplerini tanımlar şeklinde düşünebiliriz. Javascript’de interface kavramı olmadığı için TypeScript’de bir interface tanımladığınız ve compile ettiğiniz zaman, onun bir Javascript kodu üretmediğini görürsünüz. Bu noktada interface’lerin compile zamanında tipleri tanımladığını ve geliştirme aşamasında da kolaylık sağladığını belirtmek isterim.
Aşağıda TypeScript’de nasıl bir interface tanımlarız bunu basitçe görebilirsiniz. IShape diye adlandırdığımız interface’imizin getPerimeter() diye,-daha sonra içeriğini tanımlayacağımız, bir fonksiyonu var.
interface IShape { getPerimeter(): number; }
Şimdi bu interface’den yaratacağımız Square sınıfımıza bir bakalım. “implements” anahtar kelimesi ile sınıfımızın IShape interface’inden oluşacağını belirtiyoruz. Aslında burada Square sınıfımızın tipi IShape arayüzü ile tanımlı olacaktır da demiş oluyoruz.
class Square implements IShape { }
Bu noktada Visual Studio’nun verdiği bir uyarının altını çizmek isterim. Yukarıdaki gibi bir ifadede, Visual Studio, Square sınıfının getPerimeter() fonkisyonunun implement edilmediğini söyleyerek hata verecektir. TypeScript’deki interface kavramının en güzel yanı aslında bu. Javascript’de tiplerin genişletilebilirliğini yönetmek zor olduğundan, çok fazla hata yapmak mümkün olabiliyordu. Ancak TypeScript’in bu özelliği ile genişletilebilirlik özelliği tamamen bizim kontrolümüze geçmiş oluyor.
Yavaştan Square sınıfımızı biraz daha anlamlı hale getirmeye başlıyalım ve interface’mizin getPerimeter() fonkisyonunu kare için tanımlayalım.
class Square implements IShape { private length: number; constructor(l: number) { length = l; } getPerimeter(): number { return length * 4; } }
Compile ettiğimiz zaman, aşağıdaki gibi bir javascript kodunu elde edeceğiz. Dikkat ederseniz, IShape’e dair herhangi bir tanım, herhangi bir ifade yok.
var Square = (function () { function Square(l) { length = l; } Square.prototype.getPerimeter = function () { return length * 4; }; return Square; })(); window.onload = function () { var s = new Square(4); console.log(s.getPerimeter()); };
Yukarıda interface’ler TypeScript’de genişletilebilirliği sağlayan en önemli kavram demiştim. Peki nasıl yapıyoruz bunu?
Javascript, type-safe bir dil olmadığı için, execution anında TypeScript sayesinde tip ekleyip, tipleri genişletebiliriz. Mesela var olan Date tipini genişletip yeni bir metod ekleyelim. Bu metod, bulunduğumuz günün adını versin bize. Bunun için mevcut Date tipini, aynı isimle bir interface yaratıp getTodayName() metodu ile genişletiyoruz.
interface Date { getTodayName(): string; }
Bu metodun içeriğini daha sonra, Date tipinin prototpye’ları arasında implement ediyoruz. Javascript ile haşır neşir olanların oldukça tanıdık olduğu bir ifade olacaktır.
Date.prototype.getTodayName = function () { var d = new Date(); var weekday = new Array(7); weekday[0] = "Pazar"; weekday[1] = "Pazartesi"; weekday[2] = "Salı"; weekday[3] = "Çarşamba"; weekday[4] = "Perşembe"; weekday[5] = "Cuma"; weekday[6] = "Cumartesi"; var name = weekday[d.getDay()]; return name; }
Daha sonra Date tipinde bir değişken tanımladığımız zaman onun getTodayName() diye bizim yeni eklediğimiz fonksiyona da sahip olduğunu göreceğiz.
window.onload = () => { var d: Date = new Date(); console.log(d.getTodayName()); };
TypeScript’de interface kavramı basitçe böyle. OOP yaklaşımlarını Javascript tarafında uygulayabilmek için güzel bir yapı. Artık yapabilecekleriniz sizin elinizde…