Ana içeriğe geç

Seçenek API ile TypeScript

Seçenek API ile TypeScript

Bu sayfanın, Vue ile TypeScript Kullanımı hakkında bir önizleme okuduğunuzu varsaydığını belirtmek isteriz.

ipucu

Vue, Seçenek API ile TypeScript kullanımını desteklese de, Composition API aracılığıyla Vue ile TypeScript kullanılması önerilmektedir; çünkü bu, daha basit, daha verimli ve daha sağlam tür çıkarımı sunar.

Bileşen Props'larını Tiplendirme

Seçenek API'de props için tür çıkarımı, bileşenin defineComponent() ile sarmalanmasını gerektirir. Bu sayede, Vue props seçeneğine dayanarak, required: true ve default gibi ek seçenekleri dikkate alarak props'lar için türleri çıkarabilir:

import { defineComponent } from 'vue'

export default defineComponent({
// tür çıkarımı etkin
props: {
name: String,
id: [Number, String],
msg: { type: String, required: true },
metadata: null
},
mounted() {
this.name // tür: string | undefined
this.id // tür: number | string | undefined
this.msg // tür: string
this.metadata // tür: any
}
})

Ancak, çalışma zamanı props seçenekleri yalnızca bir prop'un türü olarak constructor işlevlerini destekler – iç içe özelliklere veya işlev çağrı imzalarına sahip nesneler gibi karmaşık türler belirlemenin bir yolu yoktur.

Karmaşık props türlerini belirtilmek için PropType yardımcı türünü kullanabiliriz:

import { defineComponent } from 'vue'
import type { PropType } from 'vue'

interface Book {
title: string
author: string
year: number
}

export default defineComponent({
props: {
book: {
// `Object` için daha spesifik bir tür sağla
type: Object as PropType<Book>,
required: true
},
// işlevleri de belirtebiliriz
callback: Function as PropType<(id: number) => void>
},
mounted() {
this.book.title // string
this.book.year // number

// TS Hatası: 'string' türündeki argüman
// 'number' türündeki parametreye atanamaz
this.callback?.('123')
}
})

Uyarılar

Eğer TypeScript sürümünüz 4.7'den düşükse, validator ve default prop seçenekleri için işlev değerlerini kullanırken dikkatli olmalısınız – ok işlevleri kullanmaya özen gösterin:

import { defineComponent } from 'vue'
import type { PropType } from 'vue'

interface Book {
title: string
year?: number
}

export default defineComponent({
props: {
bookA: {
type: Object as PropType<Book>,
// TypeScript sürümünüz 4.7'den düşükse ok işlevlerini kullanın
default: () => ({
title: 'Ok İşlev İfadesi'
}),
validator: (book: Book) => !!book.title
}
}
})

Bu, TypeScript'in bu işlevler içinde this'in türünü çıkarması gerekliliğini önler; bu durum, maalesef, tür çıkarımının başarısız olmasına neden olabilir. Bu, önceki bir tasarım sınırlaması idi ve şimdi TypeScript 4.7 ile geliştirilmiştir.

Bileşen Emit'lerini Tiplendirme

Bir yayılmış etkinliğin beklenen yük payload türünü emits seçeneğinin nesne sözdizimini kullanarak bildirebiliriz. Ayrıca, tüm bildirilmeyen yayılmış etkinlikler çağrıldığında bir tür hatası verecektir:

import { defineComponent } from 'vue'

export default defineComponent({
emits: {
addBook(payload: { bookName: string }) {
// çalışma zamanı doğrulaması yap
return payload.bookName.length > 0
}
},
methods: {
onSubmit() {
this.$emit('addBook', {
bookName: 123 // Tür hatası!
})

this.$emit('non-declared-event') // Tür hatası!
}
}
})

Hesaplanan Özellikleri Tiplendirme

Bir hesaplanan özellik, dönüş değerine dayanarak türünü çıkarır:

import { defineComponent } from 'vue'

export default defineComponent({
data() {
return {
message: 'Merhaba!'
}
},
computed: {
greeting() {
return this.message + '!'
}
},
mounted() {
this.greeting // tür: string
}
})

Bazı durumlarda, bir hesaplanan özelliğin türünü açıkça belirtmeniz, uygulamasının doğru olduğundan emin olmak için yararlı olabilir:

import { defineComponent } from 'vue'

export default defineComponent({
data() {
return {
message: 'Merhaba!'
}
},
computed: {
// dönen türü açıkça belirt
greeting(): string {
return this.message + '!'
},

// yazılabilir bir hesaplanan özelliği anotlayarak
greetingUppercased: {
get(): string {
return this.greeting.toUpperCase()
},
set(newValue: string) {
this.message = newValue.toUpperCase()
}
}
}
})

Açık anotlar, TypeScript'in döngü çıkarsama döngüleri nedeniyle bir hesaplanan özelliğin türünü çıkaramadığı bazı uç durumlarda da gerekli olabilir.

Olay İşleyicilerini Tiplendirme

Yerel DOM olaylarıyla çalışırken, işleyiciye geçtiğimiz argümanı doğru bir şekilde tiplendirmek faydalı olabilir. Bu örneğe bakalım:

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
methods: {
handleChange(event) {
// `event`, 'any' türüne sahip
console.log(event.target.value)
}
}
})
</script>

<template>
<input type="text" @change="handleChange" />
</template>

Tip anotasyonu olmadan, event argümanı örtülü olarak 'any' türüne sahip olacaktır. Bu ayrıca, tsconfig.json'da "strict": true veya "noImplicitAny": true varsa bir TS hatasına da yol açar. Bu nedenle, olay işleyicilerinin argümanını açıkça anotlamak önerilir. Ayrıca, event'in özelliklerine erişirken tür doğrulamaları kullanmanız da gerekebilir:

import { defineComponent } from 'vue'

export default defineComponent({
methods: {
handleChange(event: Event) {
console.log((event.target as HTMLInputElement).value)
}
}
})

Global Özellikleri Genişletme

Bazı eklentiler, app.config.globalProperties aracılığıyla tüm bileşen örneklerine global olarak erişilebilen özellikler kurar. Örneğin, veri alma için this.$http veya uluslararasılaştırma için this.$translate kurabiliriz. TypeScript ile çalışabilmesi için, Vue, TypeScript modül genişletmesi yoluyla genişletilmesi amaçlanan bir ComponentCustomProperties arayüzü sunar:

import axios from 'axios'

declare module 'vue' {
interface ComponentCustomProperties {
$http: typeof axios
$translate: (key: string) => string
}
}

Ayrıca bakınız:

Tür Genişletme Yerleşimi

Bu tür genişletmeyi bir .ts dosyasında veya proje genelinde *.d.ts dosyasında koyabiliriz. Her iki durumda da, tsconfig.json'a dahil edildiğinden emin olun. Kütüphane / eklenti yazarları için, bu dosya package.json'daki types özelliğinde belirtilmelidir.

Modül genişletmesinden faydalanmak için, genişletmenin bir TypeScript modülünde yerleştirildiğinden emin olmalısınız. Yani, en az bir üst düzey import veya export içermelidir; bu, sadece export {} olsa bile. Genişletme bir modülün dışında yerleştirilirse, orijinal türleri geçersiz kılacak, genişletecek değildir!

// Çalışmıyor, orijinal türleri geçersiz kılıyor.
declare module 'vue' {
interface ComponentCustomProperties {
$translate: (key: string) => string
}
}
// Doğru bir şekilde çalışır
export {}

declare module 'vue' {
interface ComponentCustomProperties {
$translate: (key: string) => string
}
}

Özel Seçenekleri Genişletme

Bazı eklentiler, örneğin vue-router, beforeRouteEnter gibi özel bileşen seçeneklerini destekler:

import { defineComponent } from 'vue'

export default defineComponent({
beforeRouteEnter(to, from, next) {
// ...
}
})

Uygun tür genişletmesi olmadan, bu hook'un argümanları örtülü olarak 'any' türüne sahip olacaktır. Bu özel seçenekleri desteklemek için ComponentCustomOptions arayüzünü genişletebiliriz:

import { Route } from 'vue-router'

declare module 'vue' {
interface ComponentCustomOptions {
beforeRouteEnter?(to: Route, from: Route, next: () => void): void
}
}

Artık beforeRouteEnter seçeneği uygun şekilde tiplenmiş olacaktır. Unutmayın ki bu, bir örnektir - vue-router gibi iyi tiplenmiş kütüphaneler, otomatik olarak bu genişletmeleri kendi tür tanımlarında gerçekleştirmelidir.

Ayrıca bakınız: