Having a vue3 component that displays a list of items and includes a function to delete an item raises a concern about checking parameters and specifying the array for the filter operation. The goal is to create a universal function using typescript.
<template>
<div v-for="cat in items.cats" :key="cat.id" :style="{ display: ' flex' }">
<div>{{ cat }}</div>
<button type="button" @click="deleteItem('cats', cat.id)">delete</button>
</div>
<div v-for="car in items.cars" :key="car.id" :style="{ display: ' flex' }">
<div @delete="deleteItem('cars', car.id)">{{ car }}</div>
<button type="button" @click="deleteItem('cars', car.id)">delete</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
interface Common {
id: number;
}
interface Cat extends Common {
name: string;
type: string;
}
interface Car extends Common {
model: string;
serial: string;
}
interface Item {
cats: Cat[];
cars: Car[];
anotherArray: [];
oneMoreArray: [];
oneKey: string;
}
const items = ref<Item>({
cats: [
{
id: 0,
name: 'Kitty',
type: 'home',
},
{
id: 1,
name: 'Sherhan',
type: 'jungle',
},
],
cars: [
{
id: 0,
model: 'BMW',
serial: 'X5',
},
{
id: 1,
model: 'Audi',
serial: 'Q5',
},
],
anotherArray: [],
oneMoreArray: [],
oneKey: '',
});
function deleteItem(name?: 'cats' | 'cars', id?: number) {
if (id !== undefined && name === 'cats') {
items.value.cats = items.value.cats?.filter((cat: Cat) => cat.id !== id);
}
if (id !== undefined && name === 'cars') {
items.value.cars = items.value.cars?.filter((car: Car) => car.id !== id);
}
}
</script>
Presenting this solution, utilizing keyof Item
<script setup lang="ts">
function myFunc<T>(entity: keyof Item, id?: number) {
if (id) {
(items.value[entity] as T[]) = (items.value[entity] as T[]).filter((item: Common) => item.id !== id);
}
} // Here, an error occurs: No overload matches this call.
</script>
<template>
<div v-for="cat in items.cats" :key="cat.id" :style="{ display: ' flex' }">
<div>{{ cat }}</div>
<button type="button" @click="deleteItem < Cat > ('cats', cat.id)">delete</button>
</div>
<div v-for="car in items.cars" :key="car.id" :style="{ display: ' flex' }">
<div>{{ car }}</div>
<button type="button" @click="deleteItem < Car > ('cars', car.id)">delete</button>
</div>
</template>
A more sophisticated TypeScript solution is essential for enhancing the functionality