TypeScript’te bit düzeyi (bitwise) operatörler ve union (birleşim) tür operatörü, hem isim benzerliği hem de aynı sembolü (|) paylaşmaları yüzünden sıkça karıştırılır.
Aşağıda ikisini de net örneklerle ve pratik ipuçlarıyla anlatıyorum.
Genel bakış
- Bitwise operatörler: Çalışma zamanında sayılar üzerinde bit seviyesinde işlem yapar.
- Union operatörü: Derleme zamanında tipleri birleştirir; çalışma zamanında “operatör” değildir.
Bitwise operatörler (değer düzeyi)
TypeScript, JavaScript’in bit düzeyi operatörlerini kullanır. Bu operatörler number’ları 32-bit imzalı tamsayıya dönüştürerek çalışır.
Temel operatörler
- &: Bit düzeyi VE (AND)
- |: Bit düzeyi VEYA (OR)
- ^: Bit düzeyi ÖZEL VEYA (XOR)
- ~: Bit düzeyi DEĞİL (NOT)
- <<: Sola kaydır
- : Sağa kaydır (işaret biti korunur — aritmetik kaydırma)
- : Sağa kaydır (boşlukları 0 ile doldurur — işaretsiz kaydırma)
Örnekler
const a = 0b0101; // 5 const b = 0b0011; // 3 console.log(a & b); // 0b0001 -> 1 console.log(a | b); // 0b0111 -> 7 console.log(a ^ b); // 0b0110 -> 6 console.log(~a); // 32-bit iki tümleyene göre -> -6 console.log(1 << 3); // 8 console.log(-1 >> 1); // -1 (işaret biti korunur) console.log(-1 >>> 1); // 2147483647 (işaretsiz sağ kaydırma)
Önemli notlar
- 32-bit kuralı: number’lar bitwise işlemde 32-bit’e kırpılır. Büyük sayılarda beklenmedik sonuçlar olabilir.
- İşaretsiz 32-bit’e dönüştürme: x >>> 0 kullanabilirsiniz.
- boolean ile bitwise: true | false -> 1 gibi sayıya zorlanır; genelde kaçının.
- Öncelik: <<,>>,>>> > & > ^ > | > && > ||. Parantez kullanmak güvenli.
Bit bayrakları (flags) ile pratik kullanım
const Flags = {
Read: 1 << 0, // 0b0001
Write: 1 << 1, // 0b0010
Execute: 1 << 2, // 0b0100
Admin: 1 << 3, // 0b1000
} as const;
let perms = Flags.Read | Flags.Write; // 0b0011
// Kontrol etme
const has = (p: number, f: number) => (p & f) !== 0;
console.log(has(perms, Flags.Write)); // true
// Ekleme
perms |= Flags.Execute; // 0b0111
// Kaldırma
perms &= ~Flags.Write; // 0b0101
// Tersine çevirme (toggle)
perms ^= Flags.Admin; // 0b1101
BigInt ile bitwise
- BigInt ile &, |, ^, ~, <<, >> desteklenir; >>> desteklenmez.
- Operatörlerin her iki operandı da BigInt olmalı (number ile karışmaz).
const big = (1n << 62n) | (1n << 61n); // büyük bayrak setleri // const x = 1n >>> 1n; // HATA: >>> BigInt için yok
Sayı gösterimleri
- İkili: 0b1010
- Sekizli: 0o755
- Onaltılık: 0xFF
- Ayırıcı: 1_000_000 (okunabilirlik)
Union operatörü (tip düzeyi)
Union, bir değişkenin birden fazla tipten biri olabileceğini ifade eder. Çalışma zamanında etkisi yoktur; tamamen derleme zamanı tip kontrolü içindir.
Temel kullanım
type Id = number | string;
function toId(id: Id): number {
if (typeof id === "string") {
return Number.parseInt(id, 10);
}
return id; // number
}
Narrowing (daraltma) teknikleri
- typeof, instanceof, in, literal karşılaştırmalar, kontrol akışı ile
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rect"; w: number; h: number };
function area(s: Shape) {
switch (s.kind) {
case "circle":
return Math.PI * s.radius * s.radius;
case "rect":
return s.w * s.h;
default: {
// Exhaustiveness check (asla olmamalı)
const _exhaustive: never = s;
return _exhaustive;
}
}
}
null ve undefined ile union
function len(s: string | null | undefined) {
if (!s) return 0; // null/undefined/"" hepsini yakalar
return s.length; // burası yalnızca string
}
- strictNullChecks açıkken null ve undefined’ı ayrıca ele almak gerekir.
- Non-null assertion (!), yalnızca gerçekten eminseniz: value!.length
Union vs Intersection
- Union (|): “ya o ya bu”
- Intersection (&): “hem o hem bu”
type A = { a: number };
type B = { b: string };
type U = A | B; // {a} veya {b}
type I = A & B; // {a,b} ikisi birden
Not: string & number -> never (mümkün değil)
Literal union ve daraltma
type Direction = "up" | "down" | "left" | "right";
let d: Direction = "up";
// d = "u"; // Hata
function move(dir: Direction) {
if (dir === "left" || dir === "right") { /* ... */ }
}
Union ile aşina olunması gerekenler
- Ortak olmayan alanlara erişmek için önce daraltma gerekir.
- Fonksiyon aşırı yüklemelerinde bazen union yeterlidir; bazen overloading daha iyi okunur.
- Generics ile “dağıtımlı koşullu tipler” union’lar üzerinde dağıtım yapar (Exclude, Extract gibi yardımcı tipler bu sayede çalışır).
| sembolünün üç farklı bağlamı
- Değer düzeyi: a | b -> bitwise OR (ör.: 1 | 2 === 3)
- Mantıksal: a || b -> kısa devreli mantıksal OR (boolean)
- Tip düzeyi: type T = A | B -> union tipi
Dikkat: let x = 1 | 2; ifadesi 3 üretir; union değildir. Union yalnızca tip konumunda (type bildirimlerinde ve anotasyonlarda) kullanılır.
Sık hatalar ve ipuçları
- if (perms & flag) yerine (perms & flag) !== 0 yazmak daha güvenlidir (flag 0 ise tuzak olabilir).
- Bitwise işlemler, kayan noktalı number’ı 32-bit int’e kırptığı için büyük sayılarda dikkat.
- Boolean’larda bitwise kaçının; mantıksal işlemler için && ve || kullanın.
- Öncelik karışıklığına karşı parantez kullanın: (a & b) === 0 gibi.

