TypeScript'da 'unknown' Veri Tipini Güvenli Bir Şekilde Doğrulama
TypeScript'da 'unknown' Veri Tipini Güvenli Bir Şekilde Doğrulama
TypeScript, geliştiricilerin daha güvenli ve tutarlı kod yazmasına olanak tanıyan güçlü bir tip sistemi ile bilinir. Ancak bu tip sistemi, dışarıdan gelen verilerle çalışırken bazı zorluklar yaşatır. Özellikle API yanıtları, JSON.parse() sonuçları, localStorage verileri veya üçüncü taraf kodlardan gelen veriler gibi güvenilmez giriş noktalarında, TypeScript’ın unknown tipi bu durumda sadece bir "şüpheli" değer olarak kabul edilir. Peki, bu unknown değerlerin nasıl güvenli bir şekilde doğrulanabileceğini, büyük şema kütüphaneleri olmadan nasıl sağlayabiliriz?
unknown: TypeScript'in Güvenlik Sistemi
Bir değerin unknown olduğunu belirtmek, TypeScript’in bu değerin tipini bilmediğini ve doğrulanmadan önce güvenilmez olduğunu söyler. Örneğin:
declare const input: unknown;
input.name; // Hata: 'name' property'si mevcut değil
Bu hata, TypeScript’in unknown türünden bir değerin hiçbir özelliklerine erişilmesine izin vermemesini gösterir. Bu, aslında bir güvenlik önlemdir. Çünkü bir HTTP yanıtı, doğrulanmamış bir JSON parse sonucu veya kullanıcı girişi gibi bir değerin gerçek tipini bilmiyorsak, bu değeri hemen bir User gibi bir tipe atamak doğru olmaz.
İşte bu noktada, as User gibi bir tip ataması yapmak, TypeScript’i kandırır ama gerçekten doğrulanmamış bir değeri kabul etmek demektir. Örneğin:
const input = { id: "user-1", name: 123 } as unknown;
const user = input as User; // TypeScript burada hata vermez
user.name.toUpperCase(); // 💥 Runtime hatası: 123'te toUpperCase() yok!
Bu durumda, as kelimesi bir tip sabitlemesi yapar ama runtime kontrolü yapmaz. Yani değerlerin doğru bir şekilde doğrulanması için gerçek bir doğrulama kontrolü gereklidir.
is-kit ile unknown Doğrulama
is-kit gibi küçük ve esnek kütüphaneler, unknown değerlerin güvenli bir şekilde doğrulanması için güçlü araçlar sunar. Bu kütüphane, tip kontrolü ve runtime doğrulama arasında köprü kurar. Yani:
- Tip kontrolü:
if (isUser(input))bloğu, TypeScript’einput’ınUsertüründe olduğunu söyler. - Runtime doğrulama:
isUserfonksiyonu, değerlerin gerçekten doğru olup olmadığını kontrol eder.
Örneğin:
import { isString, oneOfValues, struct } from "is-kit";
const isUser = struct({
id: isString,
name: isString,
role: oneOfValues("admin", "member"),
});
Bu yapı, unknown bir değeri doğrulamak için bir "tip koruyucu" sağlar. Eğer isUser işlevi true dönerse, TypeScript bu değerin User türüne sahip olduğunu anlar. Böylece her iki kontrol de sağlanmış olur.
Kompozisyonla Kullanım
Gerçek dünyadaki veri yapıları genellikle daha karmaşıktır. Örneğin, bir kullanıcı verisinde profili, biyografisini, etiketleri gibi alanlar olabilir. Bu durumda, kütüphane sayesinde küçük doğrulama kurallarını birleştirebiliriz:
import { arrayOf, isString, nullable, optionalKey, struct } from "is-kit";
const isProfile = struct({
displayName: isString,
bio: optionalKey(nullable(isString)),
});
const isUser = struct({
id: isString,
role: oneOfValues("admin", "member"),
profile: optionalKey(isProfile),
tags: arrayOf(isString),
});
Burada optionalKey ve nullable gibi yardımcı fonksiyonlar, farklı runtime koşullarını doğru şekilde temsil eder:
optionalKey(...): Özellik olmayabilir.nullable(...): Özellik olabilir, ancaknullolabilir.
Bu ayrımlar, uygulamanızın doğru davranışlar göstermesi için önemlidir.
safeParse ile Doğrulama Sonuçlarını Kullanma
Bazı durumlarda, doğrulama sonucunun doğruluğu ile birlikte veri de geri dönmelidir. Örneğin bir API’ye istek gönderirken, doğrulama başarısızsa 400 hata kodu dönmeli, başarılıysa kullanıcı verisi ile 200 dönmeli.
Bu durumda safeParse fonksiyonu işe yarar:
const result = safeParse(isUser, input);
if (!result.valid) {
return { status: 400 as const };
}
return {
status: 200 as const,
user: result.value,
};
safeParse, doğrulama sonucunu bir tagged nesne olarak döner:
{ valid: true, value: ... }{ valid: false }
Bu, valid property’si ile kontrol edilebilir ve TypeScript bu durumu daraltır. Ayrıca, safeParse, değeri değiştirmez, doğrulama yaparken orijinal veriyi korur. Bu, veri bütünlüğünü korumak açısından önemlidir.
JSON Verileriyle Çalışma
JSON verileri, en yaygın unknown girişleri arasındadır. JSON.parse() sonuçları any olarak döner, bu da kontrolsüz bir şekilde yayılmasına neden olur. Ancak, safeJsonParse gibi bir fonksiyon, bu işlemi güvenli hale getirir:
import { safeJsonParse } from "is-kit";
declare const body: string;
const result = safeJsonParse(body, isUser);
if (!result.valid) {
return { status: 400 as const };
}
renderUser(result.value);
Bu yapı, hem geçersiz JSON’lar hem de doğrulama hataları için aynı hata yapısını kullanır. Böylece, unknown değerler sadece bir decode sınırlarında kalır ve programın diğer kısımlarına yayılmaz.
Ekstra Anahtarlar: İzin Verilmeli mi?
Bir obje doğrularken, beklenmeyen ek anahtarlar (örneğin { username: "Neko", password: "secret", admin: true }) kabul edilip edilmemesi de önemli bir sorudur. struct ile bu durumda varsayılan olarak ek anahtarlar kabul edilir. Bu, bazı durumlarda faydalıdır, çünkü API’lerde sadece beklenen alanlar değil, ek bilgiler de gönderilebilir.
Ancak, bazı durumlarda bu ek anahtarların kabul edilmemesi istenebilir. Bu durumda, doğrulama kurallarını daha katı hale getirip, ek anahtarları reddetmek mümkündür. Ancak bu genellikle is-kit gibi kütüphanelerde özel ayarlarla sağlanır.
Sonuç
TypeScript’te unknown türünü güvenli bir şekilde doğrulamak, tip güvenliğiyle birlikte runtime güvenliği de sağlar. Büyük şema kütüphaneleri yerine, is-kit gibi küçük ve esnek araçlarla, doğrulama kurallarını kompozisyonla oluşturarak hem tip güvenliği hem de runtime kontrolü sağlanabilir.
isUsergibi bir tip koruyucu, hem TypeScript hem de runtime’da doğrulama yapar.safeParse, doğrulama sonucu ile birlikte veriyi döner.safeJsonParse, JSON parse işlemini güvenli bir şekilde yönetir.optionalKeyvenullablegibi fonksiyonlar, farklı runtime durumlarını doğru şekilde temsil eder.
Bu yaklaşımlar, TypeScript’in gücünü kullanarak hem hızlı hem de güvenli bir uygulama yazmamızı sağlar. unknown değerlerin güvenli bir şekilde doğrulanması, özellikle dış verilerle çalışan uygulamalarda hayati önem taşır.