Bir DynamoDB Tablosundan TypeScript Türleri Nasıl Üretilir
Postgres'te information_schema'yı iç gözlemler ve ondan türler üretirdiniz.
DynamoDB'nin bir eşdeğeri yoktur — ve bu eksik bir özellik değil, veri
modelinin kendisidir: DynamoDB hiçbir öğe şeması saklamaz. Hizmetin
bildiği tek öznitelikler, anahtarlarda kullanılanlardır. DescribeTable'ın
AttributeDefinitions'ı kendi kapsamı hakkında açıktır: her giriş, "tablo ve
dizin anahtar şemasındaki bir özniteliği tanımlar"
(AWS API referansı) —
tablonuzun diğer elli özniteliği hiçbir yerde kayıtlı değildir.
Dolayısıyla "DynamoDB'den TypeScript türleri üretmek" her zaman üç şeyden biri anlamına gelir: şekli kendiniz bildirin, kodda yazdığınız bir şemadan türetin veya gerçekten var olan öğelerden çıkarsayın.
Bir DynamoDB tablosu için TypeScript türlerini nasıl alırım?
Bir tablonun öğe şeklini döndüren bir API yoktur — DescribeTable yalnızca
anahtar öznitelikleri bilir. Seçenekleriniz: elle bir interface yazıp
sınırda doğrulayın (bir Zod şeması, türleri ve çalışma zamanı denetimini tek
bir yapıt yapar), yazdığınız şemanın türleri ürettiği şema-öncelikli bir
kütüphane kullanın veya şekli gerçek öğelerden çıkarsayın — betikle ya da
tabloyu tarayıp bir TypeScript arayüzü, Zod şeması veya JSON Schema dışa
aktaran DynoTable gibi bir araçla.
- Yöntem 1: arayüzü elle yazın (+ sınırda Zod)
- Yöntem 2: şema-öncelikli kütüphaneler (yazdığınız bir şemadan türler)
- Yöntem 3: verinin kendisinden çıkarsayın
Yöntem 1: arayüzü elle yazın + sınırda doğrulayın
AWS SDK öğelerinizi sizin için türleyemez. v3 Document istemcisi öğeleri
türsüz kayıtlar olarak döndürür — her GetCommand / QueryCommand sonucu,
siz aksini iddia edene kadar fiilen Record<string, unknown>'dır. Çıplak
bir as Order dönüşümü sorunsuz derlenir ve çalışma zamanında yalan söyler;
bu yüzden sağlam sürüm, arayüzü bir çalışma zamanı denetimiyle eşleştirir:
import {z} from 'zod';
const Order = z.object({
PK: z.string(), // ORDER#<id>
SK: z.string(), // META
status: z.enum(['open', 'shipped', 'cancelled']),
total: z.number(),
couponCode: z.string().optional() // sparse attribute
});
type Order = z.infer<typeof Order>;
const {Item} = await doc.send(new GetCommand({TableName: 'Orders', Key: key}));
const order = Order.parse(Item); // typed AND verifiedTek şema, iki iş: z.infer size statik türü verir, parse ona uymayan öğeyi
yakalar — ki şemasız bir depoda bu bir eğer değil, bir ne zaman meselesidir.
Püf noktası da aynı ölçüde açık: şema, tablonuzu değil, niyetinizi
belgeler. Hiçbir şey eski bir yazarın total'ı bir dize olarak saklamış
olmasını engellemez ve elle yazılmış türler, veri evrildikçe sessizce sapar.
Ham (Document-istemcisi olmayan) API çıktısıyla çalışıyorsanız, tel biçiminin
tür etiketli DynamoDB-JSON olduğunu hatırlayın ({"S": "..."}, {"N": "123"}) —
bkz. marshalling — ve şemayı yazarken bir
örneği tel biçimi ile düz biçim arasında çevirmek için
DynamoDB JSON dönüştürücüsünü kullanın.
Yöntem 2: şema-öncelikli kütüphaneler
ElectroDB ve DynamoDB-Toolbox gibi araç takımları, sapma sorununa yazma tarafından saldırır: kodda bir varlık şeması yazarsınız ve kütüphane, TypeScript türlerini türetir ve gerçekleştirdiği her okuma ve yazmada şekli zorlar. Bu, mevcut en güçlü garantidir — ama yöne dikkat edin: şemayı siz yazarsınız; kütüphane onu keşfetmez. Birini mevcut bir tabloya doğrultmak, yine önce öğe şekillerini kendiniz tersine mühendislikle çıkarmanız anlamına gelir ve kütüphanenin dışında yazılan öğeler garantilerinin dışındadır. Her varlığın ilk günden araç takımından geçtiği yeşil alan tek tablo tasarımlarında parlarlar.
Yöntem 3: türleri gerçek öğelerden çıkarsayın
Mevcut bir tablo için, zemin gerçeği veridir. Bir örneklem tarayın, şekillerin birleşimini alın:
const seen = new Map<string, Set<string>>(); // attr -> observed types
let count = 0;
let key: Record<string, unknown> | undefined;
do {
const page = await doc.send(new ScanCommand({TableName: 'Orders', ExclusiveStartKey: key}));
for (const item of page.Items ?? []) {
count++;
for (const [attr, value] of Object.entries(item)) {
const t = Array.isArray(value) ? 'array' : typeof value;
(seen.get(attr) ?? seen.set(attr, new Set()).get(attr)!).add(t);
}
}
key = page.LastEvaluatedKey;
} while (key && count < 5000);
// emit: attribute -> type union, optional if seen in < count itemsNaif sürümün hemen çarptığı gerçek dünya tuzakları:
- Seyrek öznitelikler. Bir tablodaki DynamoDB öğeleri farklı özniteliklere
sahip olabilir; öğelerin %80'inde bulunan bir öznitelik
optional'dır, eksik değil. Yalnızca varlığı değil, öznitelik başına sıklığı izleyin. - Karışık varlıklar. Bir tek tablo tasarımında
USER#veORDER#öğeleri tabloyu paylaşır — ikisi için tek bir birleştirilmiş arayüz işe yaramaz. Örneklemi tür özniteliğine göre bölümleyin ve varlık başına bir tür yayımlayın. - Tür çakışmaları. Aynı özniteliğin burada
N, şuradaSolarak saklanması gerçek (ve yaygın) bir veri hatasıdır — sessizce birini seçmek yerine bunu bir birleşim olarak yüzeye çıkarın. Tam etiket kümesi veri türleri bölümündedir. - Bir örneklem, bir örneklemdir. Yalnızca nadir öğelerde görünen öznitelikler ilk 5.000'inizde olmayabilir — ve tarama her halükârda okuma kapasitesine mal olur (query ve scan).
DynoTable'da tek tıkla çıkarsama
O çıkarsama betiği — örnekleme, sıklık izleme, iç içe yollar, varlık başına bölme — DynoTable'ın Tablo istatistikleri paneline yerleşiktir:
- Bir tablo açın, Stats düğmesine (çubuk grafik simgesi) basın ve
Index table'a tıklayın. DynoTable, tabloyu canlı ilerlemeyle bir kez
tarar ve öğelerinizin taşıdığı her özniteliği keşfeder —
commonData.statusgibi noktalı yolla iç içe olanlar dahil — türüyle ve taranan satırlar boyunca zorunlu mu isteğe bağlı mı olduğuyla birlikte. - Export'a tıklayın ve bir biçim seçin:
- TypeScript — bir
interface. - Zod — bir
z.object(...)şeması (Standard-Schema uyumlu). - JSON Schema — draft 2020-12.
- TypeScript — bir
- Panoya kopyalayın veya bir dosyaya kaydedin.

Dışa aktarım ne olduğu konusunda dürüsttür: üretilen her şema, örneklenen öğelerden çıkarsandığını belirten bir notla açılır — güçlü bir başlangıç noktası, yetkili bir sözleşme değil. İsteğe bağlılık, her özniteliğin dizinleme sırasında ne sıklıkla göründüğünü yansıtır ve birincil anahtar öznitelikleri her zaman zorunlu olarak işaretlenir. Dizinleme, normal DynamoDB okuma maliyetlerine yol açar ve Reindex, veriniz değiştikten sonra resmi tazeler.
SSS
DescribeTable'dan türler üretebilir miyim?
Yalnızca anahtar öznitelikler için. AttributeDefinitions, tablo ve dizin
anahtar şemasını kapsar — öğeleriniz hakkında başka hiçbir şey hizmet
tarafından saklanmaz, dolayısıyla iç gözlemlenecek sunucu tarafı bir şema
yoktur.
Mevcut bir üretim tablosunu türlemenin en iyi yolu nedir? Önce çıkarsayın, sonra sağlamlaştırın: gerçek şekli elde etmek için gerçek öğeleri örnekleyin (betik veya DynoTable'ın dizinlenmiş dışa aktarımı), gözden geçirin ve gelecekteki sapma sınırda yakalansın diye onu elinizde tuttuğunuz bir Zod şemasına veya şema-öncelikli bir kütüphane varlığına terfi ettirin.
Tek tabloda birden çok varlık türünü nasıl ele alırım? Varlık başına bir tür, asla tek bir birleştirilmiş tür değil. Örneklemi tür özniteliğinize (veya anahtar önekine) göre bölün ve her biri için ayrı bir arayüz üretin — bunların ayrımlı birleşimi, tablonuzun türüdür.
Üretilen türlerim zorunlu bir alanı neden isteğe bağlı diyor? Çünkü örneklenen bir öğede o alan yoktu. Şemasız bir depoda isteğe bağlılık bir bildirim değil, bir gözlemdir — o öğelerin geriye doldurulacak eski satırlar mı (bkz. geçişler) yoksa gerçekten isteğe bağlı bir öznitelik mi olduğunu kontrol edin.
Türler DynamoDB kümelerini ve ikili verileri kapsıyor mu? Bir dönüştürücü düz-JSON temsilleri seçmek zorundadır: kümeler dizilere, ikili veri kodlanmış bir dizeye dönüşür — marshalling bölümünde ele alınan aynı eşleme tuhaflıkları. Özniteliklerinizin her iki tarafta tam olarak neye benzediğini görmek için bir örneği DynamoDB JSON dönüştürücüsünden gidiş-dönüş geçirin.
Tablonuzun şeklini tahmin etmeyi bırakın — DynoTable'ı indirin, tabloyu dizinleyin ve tek tıkla bir TypeScript, Zod veya JSON Schema dışa aktarın.


