TypeScript'te bir fonksiyonu tiplemek için parametrelerin ve dönüş değerinin tipini yazarsınız: function topla(a: number, b: number): number. Fonksiyonun kendisini bir değer olarak tarif etmek için (a: number) => void gibi bir fonksiyon tipi ifadesi, özellikleri de olan çağrılabilir nesneler için call signature, farklı argüman kalıplarıyla çağrılan fonksiyonlar için overload imzaları kullanılır. İsteğe bağlı (?) ve varsayılan değerli parametreler, this parametresi ve void dönüş tipinin özel atanabilirlik kuralı da bu konunun parçasıdır.
Bu yazıda bunları sırayla ve derlenmiş örneklerle anlatıyoruz; TypeScript 6.0'ın this kullanmayan fonksiyonlardaki çıkarım değişikliğine de değiniyoruz. Örnekler TypeScript 6.0.3 ile tsc --strict --target es2022 --moduleDetection force seçenekleriyle derlendi; hata kodları ve mesajları bu derleyicinin gerçek çıktısıdır. Fonksiyonların JavaScript tarafını JavaScript fonksiyonlar ve arrow function ve default ve rest parametreler yazılarında bulabilirsiniz.
Parametre ve dönüş tipi açıklamaları

Parametre tipi parametre adından sonra, dönüş tipi parametre listesinden sonra yazılır. Parametre tipi yazılmışsa derleyici her çağrıda argümanları denetler. Tip yazmasanız bile argüman sayısı yine kontrol edilir:
function selamla(ad: string): string {
return "Merhaba, " + ad.toUpperCase() + "!";
}
selamla("ayşe"); // geçerli
selamla(42);
// TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.Dönüş tipini çoğu zaman yazmanız gerekmez; derleyici return ifadelerinden çıkarır. Handbook, bazı ekiplerin belgeleme, kazara değişiklikleri önleme ya da tercih nedeniyle yine de yazdığını belirtir. async fonksiyonların dönüş tipi Promise<T> biçiminde yazılır:
async function sayiGetir(): Promise<number> {
return 26;
}
sayiGetir().then((n) => console.log(n + 1)); // 27Bir fonksiyonun nasıl çağrılacağı bağlamdan belliyse, örneğin forEach'e verilen bir callback, parametreleri tip yazmadan da doğru tipi alır. Buna contextual typing (bağlamsal tipleme) denir. Promise tarafının ayrıntıları için async/await yazısına bakabilirsiniz.
Fonksiyon tipi ifadeleri
Bir fonksiyonu parametre olarak alırken onun tipini arrow function'a benzeyen bir sözdizimiyle yazarsınız. Bu tipe type ile ad da verebilirsiniz:
type Bicimlendirici = (deger: number) => string;
function uygula(liste: number[], fn: Bicimlendirici) {
return liste.map(fn).join(" | ");
}
console.log(uygula([1.5, 2], (d) => d.toFixed(2))); // 1.50 | 2.00type Yanlis = (string) => void;
// TS7051: Parameter has a name but no type. Did you mean 'arg0: string'?Call signature ve construct signature
JavaScript'te fonksiyonların özellikleri de olabilir. Fonksiyon tipi ifadesi özellik tanımlamaya izin vermediği için bu durumda bir nesne tipinin içine call signature yazılır. Sözdizimi küçük bir farkla ayrılır: Parametre listesi ile dönüş tipi arasında => değil : kullanılır:
type AciklamaliFonksiyon = {
aciklama: string;
(arg: number): boolean;
};
function calistir(fn: AciklamaliFonksiyon) {
console.log(fn.aciklama + " sonucu: " + fn(6));
}
function buyukMu(arg: number) {
return arg > 3;
}
buyukMu.aciklama = "3'ten büyük mü";
calistir(buyukMu); // 3'ten büyük mü sonucu: truenew ile çağrılan kurucular için call signature'ın önüne new eklenir: { new (s: string): Tarih }. Handbook, Date gibi hem new ile hem de onsuz çağrılabilen nesneler için iki imzanın aynı tipte birlikte yazılabileceğini gösterir.
İsteğe bağlı ve varsayılan parametreler

Parametre adının sonuna ? eklemek onu isteğe bağlı yapar. Tipi number yazılsa bile fonksiyonun içinde parametrenin tipi number | undefined'dır, çünkü verilmeyen argümanlar JavaScript'te undefined olur. Varsayılan değer verdiğinizde ise gövdede tip number'dır; undefined gelirse yerine varsayılan değer konur:
function yuvarla(x: number, basamak?: number) {
return basamak === undefined ? Math.round(x) : x.toFixed(basamak);
}
function kdvEkle(tutar: number, oran = 20) {
return tutar + (tutar * oran) / 100; // oran: number
}
console.log(yuvarla(3.14159), yuvarla(3.14159, 2)); // 3 3.14
console.log(kdvEkle(100), kdvEkle(100, 10), kdvEkle(100, undefined)); // 120 110 120Son çağrıda olduğu gibi isteğe bağlı bir parametreye açıkça undefined vermek her zaman geçerlidir; bu, argümanı hiç vermemekle aynı anlama gelir.
Callback tiplerinde isteğe bağlı parametre tuzağı
Callback alan bir fonksiyon yazarken parametreyi index?: number diye işaretlemek, "callback'i bir ya da iki argümanla yazabilirsiniz" anlamına gelmez. Aksine, "bu callback bazen tek argümanla çağrılabilir" demektir ve kullanıcıyı gereksiz kontrollere zorlar:
function herBiri(dizi: number[], cb: (deger: number, index?: number) => void) {
for (let i = 0; i < dizi.length; i++) cb(dizi[i], i);
}
herBiri([1, 2, 3], (d, i) => {
console.log(i.toFixed());
});
// TS18048: 'i' is possibly 'undefined'.Handbook'un kuralı şudur: Callback'i o argümanı vermeden çağırmayı gerçekten amaçlamıyorsanız callback tipinde isteğe bağlı parametre yazmayın. JavaScript'te fazla argümanlar zaten yok sayılır, bu yüzden daha az parametre alan bir fonksiyon her zaman daha çok parametre bekleyen bir fonksiyonun yerine geçebilir. Doğru tip (deger: number, index: number) => void olur.
Rest parametreler ve parametre destructuring
Sınırsız sayıda argüman alan rest parametrenin tipi T[], Array<T> ya da bir tuple olarak yazılır. Destructuring ile alınan parametrelerde tip, destructuring kalıbından sonra gelir:
function carp(n: number, ...sayilar: number[]) {
return sayilar.map((x) => n * x);
}
type ABC = { a: number; b: number; c: number };
function topla({ a, b, c }: ABC) {
return a + b + c;
}
console.log(carp(10, 1, 2, 3)); // [ 10, 20, 30 ]
console.log(topla({ a: 10, b: 3, c: 9 })); // 22Overload: aynı fonksiyonu farklı biçimlerde çağırmak
Bazı fonksiyonlar farklı sayıda ya da tipte argümanla çağrılır. TypeScript'te bunu, gövdeden önce birden fazla overload imzası yazarak ifade edersiniz. Gövdenin üzerindeki imzaya implementation signature denir ve dışarıdan görünmez; yalnızca overload imzaları çağrılabilir:
function tarihYap(zamanDamgasi: number): Date;
function tarihYap(ay: number, gun: number, yil: number): Date;
function tarihYap(ayVeyaDamga: number, gun?: number, yil?: number): Date {
if (gun !== undefined && yil !== undefined) {
return new Date(yil, ayVeyaDamga, gun);
}
return new Date(ayVeyaDamga);
}
const d1 = tarihYap(12345678);
const d2 = tarihYap(5, 5, 5);
const d3 = tarihYap(1, 3);
// TS2575: No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.Implementation imzası iki isteğe bağlı parametreyle yazılmış olsa da fonksiyon iki argümanla çağrılamaz. Aynı nedenle tek overload imzası yazıp gövdeyi parametresiz bırakırsanız fonksiyonu argümansız çağıramazsınız; derleyici TS2554 (Expected 1 arguments, but got 0.) verir. Handbook bu yüzden gövdenin üzerinde her zaman iki ya da daha fazla imza olmasını önerir. Implementation imzası tüm overload'larla uyumlu olmak zorundadır:
function donustur(x: boolean): void;
function donustur(x: string): void;
function donustur(x: boolean) {}
// TS2394: This overload signature is not compatible with its implementation signature.Overload'ların bir sınırı da her çağrının tek bir imzaya çözümlenmesidir. Değer "string ya da dizi" olabiliyorsa hiçbir imza onu karşılamaz:
function uzunluk(s: string): number;
function uzunluk(dizi: any[]): number;
function uzunluk(x: any) {
return x.length;
}
uzunluk(Math.random() > 0.5 ? "merhaba" : [0]);
// TS2769: No overload matches this call.İki overload da aynı sayıda argüman alıp aynı tipi döndürdüğü için doğru çözüm overload'u tamamen kaldırıp union parametre kullanmaktır: function uzunluk(x: any[] | string) { return x.length; }. Handbook'un kuralı: Mümkün olduğunda overload yerine union tipli parametreleri tercih edin. Union tipleri için union ve intersection yazısına bakabilirsiniz.
this parametresi
JavaScript belirtimi this adında bir parametreye izin vermez. TypeScript bu boşluğu, fonksiyonun gövdesindeki this'in tipini bildirmek için kullanır. Sahte bir ilk parametre olarak yazılır ve derlenen JavaScript'ten silinir. Callback'in hangi nesneyle çağrılacağını başka bir kodun belirlediği API'lerde yaygındır:
interface Kullanici {
id: number;
admin: boolean;
}
const kullanicilar: Kullanici[] = [
{ id: 1, admin: true },
{ id: 2, admin: false },
];
function suz(filtre: (this: Kullanici) => boolean): Kullanici[] {
return kullanicilar.filter((k) => filtre.call(k));
}
const adminler = suz(function (this: Kullanici) {
return this.admin;
});
console.log(adminler.map((k) => k.id)); // [ 1 ]Bu davranış için callback'i function ile yazmanız gerekir; handbook arrow function'larla bunun çalışmadığını belirtir, çünkü arrow function'ların kendi this'i yoktur. this'in tipi belirlenemediğinde ise noImplicitThis (strict ailesinde) hata verir:
class Dikdortgen {
en = 2;
boy = 3;
alanFonksiyonu() {
return function () {
return this.en * this.boy;
};
}
}
// TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.JavaScript'teki this kuralları için this anahtar kelimesi yazısına bakabilirsiniz.
void dönüş tipinin atanabilirlik kuralı
() => void tipindeki bir fonksiyon tipi, onu uygulayan fonksiyonun değer döndürmesini yasaklamaz. Döndürülen değer yok sayılır ve çağrının sonucu yine void tipinde kalır. Bu kural sayesinde push bir sayı döndürdüğü hâlde aşağıdaki forEach çağrısı derlenir:
type VoidFn = () => void;
const f1: VoidFn = () => true; // geçerli
const v1 = f1(); // v1: void
const kaynak = [1, 2, 3];
const hedef = [0];
kaynak.forEach((x) => hedef.push(x));
console.log(hedef); // [ 0, 1, 2, 3 ]İstisna, dönüş tipi açıkça void yazılmış fonksiyon tanımlarıdır; bunlar değer döndüremez:
const kaydet = function (): void {
return true;
};
// TS2322: Type 'boolean' is not assignable to type 'void'.void ile undefined, never ve unknown arasındaki farkları any, unknown, never ve void yazısında ele alıyoruz.
strictFunctionTypes: parametrelerin doğru denetimi
Fonksiyon tiplerini birbirine atarken parametreler de karşılaştırılır. strictFunctionTypes açıkken yalnızca string kabul eden bir fonksiyon, string | number ile çağrılabilecek bir fonksiyon tipine atanamaz; aksi hâlde sayıyla çağrıldığında çökerdi:
function yaz(x: string) {
console.log(x.toLowerCase());
}
type MetinVeyaSayi = (ns: string | number) => void;
let fn: MetinVeyaSayi = yaz;
// TS2322: Type '(x: string) => void' is not assignable to type 'MetinVeyaSayi'.Bu ayar strict ailesindedir ve TypeScript 6.0'da strict varsayılan olarak açık olduğu için ek ayar gerekmez. tsconfig belgesine göre kontrol yalnızca fonksiyon sözdizimiyle yazılmış tiplere uygulanır; { islem(x: string | number): void } gibi metot sözdizimi bu denetimin dışında kalır.
TypeScript 6.0: this kullanmayan metotlarda daha iyi çıkarım
Tipi yazılmamış parametreleri olan fonksiyonlar "bağlama duyarlı" (context sensitive) sayılır ve generic çıkarım sırasında sonraya bırakılır. Metot sözdizimiyle yazılan fonksiyonların örtük bir this parametresi olduğu için TypeScript 5.x'te bu, nesnedeki özellik sırasına bağlı tuhaf hatalara yol açabiliyordu. TypeScript 6.0 sürüm notlarına göre gövdesinde this hiç kullanılmayan bir fonksiyon artık bağlama duyarlı sayılmıyor. Aşağıdaki kod 6.0'da hatasız derlenir; sürüm notlarına göre önceki sürümlerde tuket'teki y parametresi unknown kalıyordu:
declare function cagir<T>(nesne: {
uret: (x: number) => T;
tuket: (y: T) => void;
}): void;
cagir({
tuket(y) {
return y.toFixed();
},
uret(x: number) {
return x * 2;
},
});Diğer 6.0 değişiklikleri için TypeScript 6.0 yenilikleri yazısına bakabilirsiniz.
Özet tablo
| Yapı | Sözdizimi | Ne zaman |
|---|---|---|
| Fonksiyon tipi ifadesi | (a: string) => void | Callback ve fonksiyon parametreleri |
| Call signature | { aciklama: string; (a: number): boolean } | Özellikleri olan çağrılabilir değerler |
| Construct signature | { new (s: string): Nesne } | new ile çağrılan kurucular |
| İsteğe bağlı parametre | x?: number | Argüman verilmeyebilir |
| Varsayılan parametre | oran = 20 | Eksik argümana değer atamak |
| Overload | Birden çok imza ve tek gövde | Argüman kalıbına göre farklı dönüş tipi |
| this parametresi | function (this: Kullanici) | this değerini dışarıdaki kodun belirlediği callback |
Sık yapılan hatalar

- Fonksiyon tipinde parametre adını unutmak:
(string) => voidTS7051 verir. - Callback tipinde gereksiz
?: Callback'i yazan herkes parametreyiundefinedolasılığına karşı kontrol etmek zorunda kalır. - Implementation imzasını çağrılabilir sanmak: Yalnızca overload imzaları dışarıdan görünür.
- Union yeterken overload yazmak: Aynı dönüş tipine sahip overload'lar "ya biri ya öbürü" tipindeki değerleri kabul etmez.
- Function tipini kullanmak: Handbook'a göre
Functiontipindeki değerlerin çağrılarıanydöndürür;() => voidgibi bir tip daha güvenlidir. - this tipli callback'i arrow function ile yazmak: Arrow function'ın kendi
this'i olmadığı için beklenen nesneye bağlanmaz.
Sık Sorulan Sorular
Dönüş tipini her zaman yazmalı mıyım?
Zorunlu değil; derleyici çıkarır. Dışa açılan API fonksiyonlarında yazmak, gövde değiştiğinde dönüş tipinin kazara değişmesini önler.
Overload mı generic mi?
Dönüş tipi argümanın tipine doğrudan bağlıysa generic çoğu zaman daha sadedir. Generic fonksiyonlar için TypeScript generics yazısına bakın.
Arrow function mı function mı?
Tip açısından ikisi de aynı fonksiyon tipini karşılar. Fark this davranışındadır: this parametresi gerekiyorsa function kullanmalısınız.
Fonksiyon tiplerini interface ile de yazabilir miyim?
Evet, call signature bir interface içinde de yazılabilir. Seçim kriterleri için interface ve type farkı yazısına bakın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: TypeScript öğrenme rehberi · any, unknown, never ve void · TypeScript generics · Union ve intersection tipleri · JavaScript fonksiyonlar · JavaScript this · TypeScript ileri seviye yazısı