\n \u003CButton text=\"Add Todo\" />\n \u003C/form>\n\u003C/template>",{"content":68,"type":24},"Here we have an emit. The syntax is much more verbose than the standard way to declare runtime emits. But with this we get type checks, so if we accidentally pass a number or an object we'll see the error before running the code.\n\nCheck out the props on the \u003Ccode class=\"ic\">TextInput\u003C/code> component. Take out the id prop or pass a number to the label prop and you'll see TypeScript in action. We'll see the error before we run the code.\n\n\u003Ca class=\"link\" href=\"https://vuejs.org/guide/typescript/composition-api.html#typing-component-emits\" target=\"_blank\">Read more about typing emits\u003C/a>",{"content":70,"type":21},"\u003Ch2>Todo.vue\u003C/h2>",{"content":72,"type":24},"There's one more component before putting everything together. But there's nothing new here. I'm using the normal way to define emits since we're not passing anything to it.",{"content":74,"type":35,"caption":36,"lang":37},"\u003Cscript setup lang=\"ts\">\nimport Button from './Button.vue';\nconst props = defineProps\u003C{\n todo: string\n}>();\n\nconst emit = defineEmits(['delete']);\n\u003C/script>\n\n\u003Ctemplate>\n \u003Cli class=\"todo-wrapper\">\n \u003Cspan class=\"todo\">{{ todo }}\u003C/span>\n \u003CButton \n @click=\"$emit('delete')\" \n text=\"Delete\"\n variant=\"danger\"\n />\n \u003C/li>\n\u003C/template>",{"content":76,"type":21},"\u003Ch2>App.vue\u003C/h2>",{"content":78,"type":24},"Finally we can put everything together.\n\nFirst we have the TodoForm component from earlier. We listen for it's emit and then call \u003Ccode class=\"ic\">addTodo\u003C/code>\n\nBeneath the form, we have TransitionGroup that acts as a 'ul' tag. Inside it we loop through the todos array, passing the todo data as a prop to our \u003Ccode class=\"ic\">Todo.vue\u003C/code>.\n\nRemember \u003Ccode class=\"ic\">Todo.vue\u003C/code> had a button that emits 'delete'. When that triggers we call \u003Ccode class=\"ic\">spliceTodo\u003C/code>.",{"content":80,"type":35,"caption":36,"lang":37},"\u003Cscript setup lang=\"ts\">\nimport { ref } from 'vue'\nimport TodoForm from './components/TodoForm.vue';\nimport Todo from './components/Todo.vue';\n\ninterface TodoItem {\n id: string,\n text: string\n}\n\nconst todos = ref\u003CTodoItem[]>([]);\n\nfunction addTodo(todo: string){\n todos.value.push({\n id: crypto.randomUUID(),\n text: todo\n });\n}\n\nfunction spliceTodo(id: string){\n const idx = todos.value.findIndex(todo => todo.id === id);\n todos.value.splice(idx, 1);\n}\n\u003C/script>\n\n\u003Ctemplate>\n \u003CTodoForm @submit=\"addTodo\" />\n\n \u003CTransitionGroup tag=\"ul\">\n \u003CTodo \n v-for=\"todo in todos\" :key=\"todo.id\"\n :todo=\"todo.text\"\n @delete=\"spliceTodo(todo.id)\" \n />\n \u003C/TransitionGroup>\n\u003C/template>",{"content":82,"type":21},"\u003Ch3>Typing Refs\u003C/h3>",{"content":84,"type":24},"Let's check out this snippet, since it's the first time I had to type a ref. ",{"content":86,"type":35,"caption":36,"lang":42},"interface TodoItem {\n id: string,\n text: string\n}\n\nconst todos = ref\u003CTodoItem[]>([]);",{"content":88,"type":24},"First we have the interface, which we've seen before.\n\nWhen declaring the ref, before the initial value we put \u003Ccode class=\"ic\"><TodoItem[]>\u003C/code>. This is telling TypeScript that this ref is an array and it can only take objects that fit the shape of the TodoItem interface. If we try to pass it something else we'll get an error.",{"content":90,"type":21},"\u003Ch2>Conclusion\u003C/h2>",{"content":92,"type":24},"This was meant to be a really small project so I wrapped things up here. We ran into several new situations like typing props, emits, and refs.\n\nEven with this small project I saw the benefits of TypeScript.\n\nOne thing I haven't mentioned that's really nice is that sometimes when using Vue I would forget to put \u003Ccode class=\"ic\">.value\u003C/code> and it would take me forever to figure out what's going on. With TypeScript that's not a problem because it will let you know immediately. This is reason enough for me to consider using TypeScript in future Vue projects.\n\nFor the next TypeScript post, I'll probably look into using it without Vue and Vite just to see what's actually going on.\n\nUntil next time.","posted","concept","2025-09-02T05:11:20.676Z","2025-09-04T19:04:42.653Z",0,"09/02/2025",["Reactive",100],{"$scolor-mode":101},{"preference":102,"value":102,"unknown":103,"forced":104},"system",true,false,["Set"],["ShallowReactive",107],{"$fmEuZkG9Kl9Gbwks2ziDdxa6SR1x3L_y_2Gn9Drf6kus":-1},"/"]