Vue.js - jak prawidłowo typować eventy?
Vue.js 2.6, Typescipt, @vue/composition-api
Czym są Custom Eventy?
Custom Eventy to eventy, które emituje komponent Vue. Nie są to natywne eventy DOM, tylko nasze własne. Przykład:
<button @click="$emit('increaseBy', 1)">
Increase by 1
</button>
Tutaj takim Custom Eventem jest increaseBy, która przyjmuje payload o wartości 1. Komponent-rodzic może nasłuchiwać na ten event w taki sposób:
<MyButton @increase-by="increaseCount" />
W czym problem?
W komponencie MyButton chcemy otypować event, który emitujemy, aby komponent-rodzic zawsze dostawał prawidłowe dane, i mógł na nich bezpiecznie operować.
Na ten moment komponent MyButton w metodzie increaseCount zakłada, że payload to zawsze number. Bez dodatkowej weryfikacji w komponencie MyButton możemy mieć sytuację, gdy przez przypadek wprowadzimy na przykład emitowanie "1" zamiast 1 i mamy problem. Sytuacja jeszcze bardziej się komplikuje, gdy emitujemy obiekt z wieloma właściwościami.
W dokumentacji Vue 3 jest informacja jak typować custom eventy przy użyciu tagu <script setup>. Natomiast w Vue w wersji < 2.7 nie ma tagu <script setup>, tym samym nie oficjalnego sposobu na typowanie custom eventów.
Rozwiązanie
Komponent w którym chcemy otypować emitowany event, musi zawierać pole emits jako obiekt. Na podstawie przykładu powyżej, będzie to wyglądać następująco:
export default defineComponent({
emits: {
increaseBy: (payload: number) => true
}
})
Od teraz Typescript nam podpowiada, że podczas emitowania eventu, wartość musi być number.
=> true oznacza, że Vue walidacja eventu zawsze przechodzi. W tym miejscu możemy dodać dodatkowe sprawdzenie emitowanego payload w czasie runtime'u.