# 2026'da TypeScript ile Vue 3: Tip Güvenli Props, Emits ve Composables > Vue 3 bileşenlerini TypeScript ile tip güvenli hâle getirmenin pratik rehberi: generic defineProps, tuple defineEmits, tiplenmiş composables, defineModel ve InjectionKey ile mülakat soruları. - Published: 2026-07-07 - Updated: 2026-07-07 - Author: SharpSkill - Tags: Vue 3, TypeScript, defineProps, Composables, Frontend - Reading time: 8 min --- 2026'da TypeScript ile birlikte kullanılan Vue 3, props, olaylar ve yeniden kullanılabilir mantık genelinde tam statik tip denetimi sağlar. ` ``` `role` prop'u artık iki string literaliyle sınırlandırılmıştır; bu nedenle `role="guest"` geçmek derlemede hata verir. TypeScript ile `defineProps`'a başvurmanın temel nedeni budur: [resmi Vue TypeScript rehberi](https://vuejs.org/guide/typescript/composition-api.html) generic biçimi ` ``` Vue 3.5, bugün daha kısa olan **reaktif prop destructuring**'i kararlı hâle getirdi. `defineProps` sonucunu destructure edip aynı ifadede bir varsayılan atamak tamamen reaktif kalır — derleyici, arka planda her erişimi yeniden `props.x`'e yazar. ```vue ``` > **Destructure edilmiş props'ta reaktiflik tuzağı** > > Destructure edilmiş props, şablonda ve `computed` içinde reaktif kalır; ancak destructure edilmiş bir değeri doğrudan `watch`'a veya bir composable'a geçirmek onu yalnızca bir kez okur ve reaktif bağı koparır. Bir ref gerektiğinde bu değeri bir getter içine sarın — `watch(() => color, ...)` — veya `toRef(props, 'color')` ile dönüştürün. Bu, yaygın bir mülakat tuzağıdır: adaylar destructure edilmiş değişkenin düz bir değer olduğunu varsayar; oysa derleyici aslında her okumayı yeniden `props.color`'a yönlendirmiştir. ## defineEmits ile tip güvenli emits Olaylar, props ile aynı titizliği hak eder. Generic `defineEmits`, her olay adını ve yükünü bir tuple olarak tanımlayarak üst bileşene otomatik tamamlama, alt bileşene ise doğru argümanların yayıldığına dair derleme zamanı denetimi sağlar. ```vue ``` Bu tuple biçimi, eski çağrı imzası sözdizimini (`(e: 'search', q: string): void`) yerini aldı; çünkü daha okunaklıdır ve aşırı yükleme olmadan birden çok olayı destekler. Bir olay veri taşımıyorsa, boş bir tuple `[]` bunu açıkça belgeler. Tiplenmiş emits'i tiplenmiş props ile eşleştirmek, tüm genel arayüzü çalışma zamanından önce doğrulanabilir bileşenler üretir — [Vue Composition API rehberinde](/blog/vue-nuxt/vue-3-composition-api-complete-guide) ele alınan aynı disiplin. ## Yeniden kullanılabilir mantık için composables tipleme Composables düz fonksiyonlardır, bu yüzden sıradan TypeScript kurallarına uyarlar — ancak birkaç kural onları ergonomik tutar. Çıkarım açık olmadığında `Ref` tiplerini açıkça döndürün ve bir composable, bir API yanıtı gibi rastgele veriyi sardığında generic kullanın. ```ts // useFetch.ts import { ref, type Ref } from 'vue' interface UseFetchReturn { data: Ref error: Ref loading: Ref } // Generic flows through to the caller's typed data export function useFetch(url: string): UseFetchReturn { const data = ref(null) as Ref const error = ref(null) const loading = ref(true) fetch(url) .then((r) => r.json()) .then((json: T) => { data.value = json }) .catch((e: Error) => { error.value = e }) .finally(() => { loading.value = false }) return { data, error, loading } } ``` Çağrı noktasında generic parametre, `data`'yı hiçbir ek açıklama olmadan tamamen tiplenmiş hâle getirir: ```ts // UserList.vue (script setup) interface User { id: number; name: string } // data is Ref — inferred from the generic const { data: users, loading } = useFetch('/api/users') ``` Döndürülen nesneyi açıkça tipleme (`UseFetchReturn`) o birkaç fazladan satıra değer: sözleşmeyi belgeler, iç ref'lerin kazara sızmasını önler ve tüketicilere içe aktarılacak tek bir tip sunar. Argüman aşırı yüklemeleri ve yaşam döngüsüne duyarlı temizlik gibi daha derin composable desenleri için [gelişmiş Vue composables rehberine](/blog/vue-nuxt/advanced-vue-3-composables-reusable-patterns) bakın. ## İki yönlü bağlama için defineModel tipleme Vue 3.4'ten beri kararlı olan `defineModel`, eski `modelValue` prop'unu ve `update:modelValue` emit'ini tek bir yazılabilir ref'e daraltır. Generic parametresi bağlamanın her iki yönünü aynı anda tipler. ```vue ``` Adlandırılmış modeller — `defineModel('title')` — `v-model:title` ile eşlenir ve aynı tiplemeyi alır. Bu, manuel prop-ve-emit deseninin gizlediği tüm bir uyumsuz yük hataları sınıfını ortadan kaldırır. ## Şablon ref'lerini ve bileşen örneklerini tipleme Bir DOM düğümüne veya alt bileşene `ref` üzerinden erişmek, tiplenmemiş Vue kodunun en sık `any`'ye düştüğü yerdir. Çözüm, `useTemplateRef`'i (Vue 3.5+) veya `ref`'in kendisini eleman tipiyle parametreleştirmektir; böylece özellik erişimi gerçek DOM arayüzüne karşı denetlenir. ```vue ``` Bir alt bileşene yapılan referans için `InstanceType`, bileşenin genel tipini çıkararak alt bileşenin `defineExpose` aracılığıyla bildirdiği her şeyi açığa çıkarır. Bu, üstten alta metot çağrılarının tahmin edilmek yerine tamamen denetlenmesini sağlar. ```vue ``` ## InjectionKey ile tip güvenli provide ve inject Bileşen ağacı boyunca bağımlılık enjeksiyonu, anahtar tip bilgisini taşımadıkça bu bilgiyi yitirir. `InjectionKey`, bir değerin tipini anahtarına bağlayan tiplenmiş bir semboldür; böylece `provide` ve `inject` manuel dönüşüm olmadan senkron kalır. ```ts // theme-key.ts import type { InjectionKey, Ref } from 'vue' export interface ThemeContext { mode: Ref<'light' | 'dark'> toggle: () => void } // The key permanently associates the ThemeContext type with this symbol export const ThemeKey: InjectionKey = Symbol('theme') ``` ```ts // provider (script setup) — value must match ThemeContext or it fails to compile provide(ThemeKey, { mode, toggle }) // consumer — theme is inferred as ThemeContext | undefined const theme = inject(ThemeKey) theme?.toggle() ``` Şekli `ThemeContext` ile eşleşmeyen bir değer sağlamak, enjeksiyon noktasında bir derleme hatasıdır; bu da uzak bileşenler arasındaki tutarsızlığı üretime ulaşmadan yakalar. ## Sık sorulan Vue TypeScript mülakat soruları Mülakatçılar, adayın derleme zamanı tipleri ile çalışma zamanı davranışı arasındaki sınırı anlayıp anlamadığını yoklar. Sıkça tekrarlanan birkaç soru ve keskin yanıtları: - **Çalışma zamanı nesne biçimi yerine neden `defineProps()` tercih edilir?** Generic props, çalışma zamanı bildirimlerinin ifade edemediği union tiplerini, fonksiyon imzalarını ve iç içe şekilleri ifade eder ve tekrarlanan tip/çalışma zamanı tanımlarını ortadan kaldırır. - **Destructure edilmiş props reaktif midir?** Vue 3.5+ ile evet, çünkü derleyici erişimi `props.x`'e yeniden yazar. Ancak `watch`'a veya bir composable'a geçirilen destructure edilmiş *değerler* bir kez okunur — bir getter veya `toRef` kullanın. - **Yükü olmayan bir olay nasıl tiplenir?** Boş bir tuple ile: `defineEmits<{ close: [] }>()`. - **`defineModel` neyin yerini alır?** `modelValue` prop'u ve `update:modelValue` emit çiftini; tek bir tiplenmiş yazılabilir ref hâlinde birleştirir. Bu konuları gerçek bir soru bankasına karşı çalışmak, mülakatların ödüllendirdiği refleksleri keskinleştirir — [Vue composables mülakat modülü](/technologies/vue-nuxt/interview-questions/vue-composables) tam olarak bu desenleri çalıştırır. Araçlar da önemlidir: tip hatalarının birleştirmeyi engellemesi için CI'da `vue-tsc` çalıştırın ve composable generic'leri işin içine girdiğinde [TypeScript el kitabına](https://www.typescriptlang.org/docs/handbook/2/generics.html) başvurun. Editör deneyimi, bu makroları okuyup hataları yerinde gösteren [Vue'nun resmi Volar aracıyla](https://github.com/vuejs/language-tools) sağlanır. ## Sonuç - Çalışma zamanı bildirimlerinin yakalayamadığı union tiplerini, isteğe bağlı alanları ve callback prop'larını ifade etmek için generic `defineProps()` kullanın. - Vue 3.5+ ile satır içi varsayılanlar taşıyan reaktif prop destructuring'i tercih edin ve ortak bir varsayılanlar nesnesi daha anlaşılır olduğunda yalnızca `withDefaults`'a başvurun. - Yüklerin hem alt hem üst bileşende derleme zamanında denetlenmesi için olayları `defineEmits`'in tuple biçimiyle tipleyin. - Composable dönüş tiplerini açıkça açıklayın ve çağıranın sağladığı veri tiplerini baştan sona iletmek için generic kullanın. - İki yönlü bağlama için `defineModel()` benimseyin; böylece prop-artı-emit tekrarını tek bir tiplenmiş ref'e daraltırsınız. - Tip gerilemelerinin üretime ulaşmak yerine build'i durdurması için sürekli entegrasyonda `vue-tsc` çalıştırın. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/vue-nuxt/vue-3-typescript-type-safe-props-emits-composables