Tip dönüşümü (type coercion), JavaScript'in bir değeri işlemin beklediği tipe çevirmesidir. Açık dönüşüm için String(x), Number(x) ve Boolean(x) kullanılır. Örtük dönüşüm ise operatörler ve koşullar tarafından kendiliğinden yapılır: "5" - 2 sonucu 3, "5" + 2 sonucu "52" olur. Koşullarda yalnızca sekiz değer yanlış (falsy) sayılır: false, 0, -0, 0n, "", null, undefined ve NaN.
Bu yazıda string, number ve boolean dönüşüm kurallarını, + operatörünün özel durumunu ve nesnelerin ilkel değere nasıl çevrildiğini çalıştırılmış örneklerle anlatıyoruz. Tiplerin kendisini veri tipleri yazısında ele aldık.
Açık ve örtük dönüşüm

JavaScript zayıf tipli bir dildir: tipler uyuşmadığında çoğu zaman hata vermek yerine dönüşüm yapar. Bu dönüşümü kendiniz istediğinizde (Number("42")) açık, dil sizin yerinize yaptığında ("42" * 1) örtük dönüşümden söz edilir. İkisi de aynı kuralları uygular; fark, kodu okuyan kişinin dönüşümü görüp göremediğidir. Okunabilirlik için açık dönüşümü tercih edin.
| Hedef tip | Açık dönüşüm | Aynı kuralları uygulayan kısa yazım |
|---|---|---|
| String | String(x) | `${x}` (Symbol için hata verir) |
| Number | Number(x) | +x (BigInt için hata verir) |
| Boolean | Boolean(x) | !!x |
Tablodaki kısa yazımlar aynı dönüşüm algoritmasını kullanır, ancak küçük farkları vardır. Bu farklar aşağıdaki bölümlerde örneklerle gösteriliyor.
String'e dönüşüm
Metne dönüşüm kuralları basittir: undefined "undefined", null "null", boolean değerler "true" veya "false" olur; sayılar ve BigInt'ler onluk tabanda yazılır. Symbol değerleri örtük olarak metne çevrilemez ve TypeError fırlatır. Nesneler önce ilkel değere çevrilir.
console.log(String(123)); // 123
console.log(String(null)); // null
console.log(String(undefined)); // undefined
console.log(String(10n)); // 10
console.log(`${[1, 2, 3]}`); // 1,2,3
const sembol = Symbol("id");
console.log(String(sembol)); // Symbol(id)
try {
console.log(`${sembol}`);
} catch (e) {
console.log(e.name); // TypeError
}Örnekte görüldüğü gibi String() Symbol için hata vermez, template literal ise verir. MDN, metne çevirmek için template literal veya String() kullanmanızı, "" + x kalıbından kaçınmanızı önerir; çünkü + operatörü değeri metne değil önce ilkel değere çevirir ve bazı nesnelerde farklı sonuç üretir.
Number'a dönüşüm

Sayıya dönüşüm kuralları en çok sürpriz barındıranlardır:
| Değer | Number() sonucu | Not |
|---|---|---|
| undefined | NaN | |
| null | 0 | undefined ile farklı davranır |
| true / false | 1 / 0 | |
| "" veya " " | 0 | boş veya yalnızca boşluk |
| " 42 " | 42 | baştaki ve sondaki boşluk atılır |
| "0x1F" | 31 | onaltılık sayı yazımı tanınır |
| "1_000" | NaN | sayı ayırıcı kabul edilmez |
| "12px" | NaN | metnin tamamı sayı olmalı |
| 10n | 10 | Number() çevirir, +10n ise TypeError verir |
| [] | 0 | önce "" metnine çevrilir |
| {} | NaN | önce "[object Object]" metnine çevrilir |
console.log(Number(""), Number(" 42 "), Number("0x1F")); // 0 42 31
console.log(Number("1_000"), Number("12px")); // NaN NaN
console.log(Number(null), Number(undefined)); // 0 NaN
console.log(+"3.5", +true); // 3.5 1
console.log(Number(10n)); // 10
try {
console.log(+10n);
} catch (e) {
console.log(e.name); // TypeError
}
console.log(parseInt("12px"), parseFloat("3.5kg")); // 12 3.5Tekli artı operatörü (+x) Number(x) ile aynı adımları izler; tek fark BigInt için hata vermesidir. parseInt() ve parseFloat() ise yalnızca metinleri çevirir ve baştan okuyabildiği kadarını alır. parseInt() ondalık noktayı, parseFloat() ise 0x önekini tanımaz. Sayıların sınırları ve hassasiyet için Number ve BigInt yazısına bakın.
+ operatörü: toplama mı birleştirme mi?
Aritmetik operatörlerin çoğu (-, *, /, %) işlenenleri sayıya çevirir. + ise iki işi birden yapar: işlenenler önce ilkel değere çevrilir, taraflardan biri metinse birleştirme, değilse sayısal toplama yapılır. İşlemler soldan sağa değerlendirildiği için sıralama sonucu değiştirir.
console.log("5" - 2); // 3
console.log("5" * "2"); // 10
console.log("5" + 2); // 52
console.log(1 + 2 + "3"); // 33
console.log("1" + 2 + 3); // 123
console.log(true + 1); // 2
console.log([] + []); // (boş metin)
console.log({} + []); // [object Object]Boolean'a dönüşüm: truthy ve falsy

if, while, üçlü operatör ve !, &&, || gibi mantıksal operatörler değerleri boolean olarak yorumlar. Kural kısadır: aşağıdaki sekiz değer false'a, geri kalan her şey true'ya dönüşür. Yanlış sayılan değerlere falsy, doğru sayılanlara truthy denir.
| Falsy değer | Tipi |
|---|---|
| false | Boolean |
| 0 ve -0 | Number |
| NaN | Number |
| 0n | BigInt |
| "" (boş metin) | String |
| null | Null |
| undefined | Undefined |
Tüm nesneler truthy'dir: boş dizi [], boş nesne {} ve hatta new Boolean(false) bile. "0" ve "false" gibi metinler de boş olmadıkları için truthy'dir. Açık dönüşüm için Boolean(x) ya da çift değil operatörü !!x kullanılır; ikisi aynı sonucu verir. Boolean dönüşümü nesneler için kullanıcı tanımlı metotları çağırmaz. (Tarayıcılardaki eski ve standart dışı document.all nesnesi bu kuralın tek istisnasıdır.)
const degerler = [0, "", "0", "false", [], {}, null, NaN, 0n, " "];
for (const d of degerler) {
console.log(JSON.stringify(String(d)), Boolean(d));
}
// "0" false
// "" false
// "0" true
// "false" true
// "" true
// "[object Object]" true
// "null" false
// "NaN" false
// "0" false
// " " trueTruthy olmak, == true olmak demek değildir
Koşulda doğru sayılmak ile == true sonucu farklı kurallara dayanır. [] truthy'dir ama [] == false da doğrudur, çünkü == diziyi önce "" metnine, sonra sayıya çevirir. Benzer şekilde "0" truthy'dir ama "0" == false doğrudur; null ve undefined ise falsy olmalarına rağmen false'a gevşek olarak eşit değildir.
if ([]) console.log("[] truthy"); // [] truthy
console.log([] == false); // true
console.log(Boolean("0"), "0" == false); // true true
console.log(Boolean(null), null == false); // false falseBu yüzden boolean karşılaştırma yaparken == true yazmak yerine değeri doğrudan koşula koyun ya da === kullanın. Ayrıntılar için eşitlik operatörleri yazısına bakın.
Nesneler ilkel değere nasıl çevrilir?
Bir nesne metin, sayı veya genel bir ilkel değer beklenen yerde kullanıldığında JavaScript sırayla şu metotlara bakar: varsa [Symbol.toPrimitive](), ardından valueOf() ve toString(). Sıra bağlama göre değişir:
- Genel ilkel dönüşüm (
+ve==): ipucu"default"; öncevalueOf(), sonratoString(). - Sayısal dönüşüm (
Number(), aritmetik): ipucu"number"; öncevalueOf(), sonratoString(). - Metin dönüşümü (
String(), template literal): ipucu"string"; öncetoString(), sonravalueOf().
[Symbol.toPrimitive]() tanımlıysa her zaman önceliklidir ve ilkel bir değer döndürmek zorundadır. Yerleşik nesnelerden yalnızca Date ve Symbol bu metodu kendine göre tanımlar; Date, "default" ipucunu "string" gibi yorumlar.
const fiyat = {
[Symbol.toPrimitive](ipucu) {
if (ipucu === "number") return 250;
if (ipucu === "string") return "250 TL";
return "varsayılan";
},
};
console.log(+fiyat); // 250
console.log(`${fiyat}`); // 250 TL
console.log(fiyat + ""); // varsayılan
const sepet = { valueOf() { return 3; } };
console.log(sepet * 2); // 6Symbol tabanlı bu protokol hakkında daha fazla bilgi için Symbol nedir yazısına göz atabilirsiniz.
Sık yapılan hatalar
- Metin olarak gelen sayıları toplamak:
+birleştirme yapar; önceNumber()ile çevirin. - Geçerli bir
0veya""değerini falsy diye elemek:deger || varsayilanyazımı 0'ı da varsayılanla değiştirir. Yalnızcanullveundefinediçin varsayılan istiyorsanız??kullanın; bkz. nullish coalescing. parseInt()ileNumber()'ı eşdeğer sanmak:parseInt("12px")12 verir,Number("12px")NaNverir. Hangisinin size uygun olduğunu bilinçli seçin.- BigInt'i
+ile sayıya çevirmek:TypeErroralırsınız;Number()kullanın ve hassasiyet kaybını göze alın. "false"metninin yanlış sayılacağını düşünmek: boş olmayan her metin truthy'dir.
Sık Sorulan Sorular
Number() ile parseInt() arasındaki fark nedir?
Number() metnin tamamını bir sayı olarak yorumlamaya çalışır, başaramazsa NaN döndürür. parseInt() metni baştan okur, ilk geçersiz karakterde durur ve o ana kadar okuduğu tam sayıyı döndürür.
Boş dizi neden truthy?
Boolean dönüşümünde tüm nesneler true olur ve diziler de nesnedir. Bir dizinin boş olup olmadığını dizi.length === 0 ile kontrol edin.
!! operatörü ne işe yarar?
İlk ! değeri boolean'a çevirip tersine çevirir, ikincisi tekrar tersine çevirir. Sonuç Boolean(x) ile aynıdır.
Örtük dönüşümden tamamen kaçınabilir miyim?
Tamamen değil, ama etkisini azaltabilirsiniz: girdileri dışarıdan aldığınız noktada açıkça dönüştürün, karşılaştırmalarda === kullanın ve koşullarda hangi değerlerin falsy olduğunu bilerek yazın. Statik tip denetimi isterseniz TypeScript bu tür hataların bir kısmını derleme aşamasında yakalar.
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: JavaScript öğrenme rehberi · JavaScript veri tipleri · Eşitlik operatörleri · Optional chaining ve nullish coalescing · Number ve BigInt