Skip to main content
vue-typescript Provides Vue 3 + TypeScript patterns — Composition API, script setup, Pinia, Vue Router, composables. Use when building Vue apps or wiring reactive state.
Ir para a instalação Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/MadAppGang/magus --skill vue-typescriptO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Mais deste repositório Picks the browser-use agent brain LLM per task. Use when choosing a model for retry_with_browser_use_agent or a cloud session, or the user mentions a cheap, slow, or smart model.
Reference for the Browser Use MCP tools — parameters, returns, session lifecycle. Use when navigating, clicking, typing, evaluating JS, or extracting page content.
Visual UI debugging — screenshot capture and analysis, responsive layout checking at multiple viewport sizes, CSS validation via DOM state, visual regression detection, before/after state comparison.
SOC
Baseado na classificação ocupacional SOC
name vue-typescript description Provides Vue 3 + TypeScript patterns — Composition API, script setup, Pinia, Vue Router, composables. Use when building Vue apps or wiring reactive state. disable-model-invocation true
Vue 3 + TypeScript Patterns
Overview
Modern Vue 3 patterns with TypeScript and Composition API for building robust applications.
Component Patterns
Script Setup with TypeScript
<script setup lang="ts">
import { ref, computed } from 'vue';
interface Props {
title: string;
count?: number;
}
const props = withDefaults(defineProps<Props>(), {
count: 0,
});
const emit = defineEmits<{
(e: 'update', value: number): void;
(e: 'close'): void;
}>();
const localCount = ref(props.count);
const doubled = computed(() => localCount.value * 2);
function increment() {
localCount.value++;
emit('update', localCount.value);
}
</script>
<template>
<div>
<h2>{{ title }}</h2>
<p>Count: {{ localCount }} (doubled: {{ doubled }})</p>
<button @click="increment">Increment</button>
</div>
</template>
Generic Components
<script setup lang="ts" generic="T">
interface Props {
items: T[];
selected?: T;
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: 'select', item: T): void;
}>();
</script>
<template>
<ul>
<li
v-for="(item, index) in items"
:key="index"
:class="{ selected: item === selected }"
@click="emit('select', item)"
>
<slot :item="item" />
</li>
</ul>
</template>
Composables
Basic Composable
import { ref, computed } ;
{
?: ;
?: ;
?: ;
}
( ) {
{ initial = , min, max } = options;
count = (initial);
= ( ) => {
(max === || count. < max) {
count. ++;
}
};
= ( ) => {
(min === || count. > min) {
count. --;
}
};
= ( ) => {
count. = initial;
};
isAtMin = ( min !== && count. <= min);
isAtMax = ( max !== && count. >= max);
{
count,
increment,
decrement,
reset,
isAtMin,
isAtMax,
};
}
from
'vue'
interface
UseCounterOptions
initial
number
min
number
max
number
export
function
useCounter
options : UseCounterOptions = {}
const
0
const
ref
const
increment
if
undefined
value
value
const
decrement
if
undefined
value
value
const
reset
value
const
computed
() =>
undefined
value
const
computed
() =>
undefined
value
return
Data Fetching Composable
import { ref, watchEffect, type Ref } from 'vue' ;
interface UseFetchReturn <T> {
data : Ref <T | null >;
error : Ref <Error | null >;
loading : Ref <boolean >;
refetch : () => Promise <void >;
}
export function useFetch<T>(url : string | Ref <string >): UseFetchReturn <T> {
const data = ref<T | null >(null ) as Ref <T | null >;
const error = ref<Error | null >(null );
const loading = ref (false );
async function fetchData ( ) {
const urlValue = typeof url === 'string' ? url : url.value ;
loading.value = true ;
error.value = null ;
try {
const response = await fetch (urlValue);
if (!response.ok ) throw new Error (`HTTP ${response.status} ` );
data.value = await response.json ();
} catch (e) {
error.value = e instanceof Error ? e : new Error ('Unknown error' );
} finally {
loading.value = false ;
}
}
watchEffect (() => {
fetchData ();
});
return { data, error, loading, refetch : fetchData };
}
State Management (Pinia)
Store Definition
import { defineStore } from 'pinia' ;
import { ref, computed } from 'vue' ;
import type { User } from '@/types' ;
export const useUserStore = defineStore ('user' , () => {
const users = ref<User []>([]);
const currentUserId = ref<string | null >(null );
const loading = ref (false );
const currentUser = computed (() =>
users.value .find (u => u.id === currentUserId.value )
);
const userCount = computed (() => users.value .length );
async function fetchUsers ( ) {
loading.value = true ;
try {
const response = await api.getUsers ();
users.value = response.data ;
} finally {
loading.value = false ;
}
}
function setCurrentUser (userId : string ) {
currentUserId.value = userId;
}
return {
users,
currentUserId,
loading,
currentUser,
userCount,
fetchUsers,
setCurrentUser,
};
});
Using Store in Components <script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useUserStore } from '@/stores/userStore';
const store = useUserStore();
// Destructure reactive state
const { users, loading, currentUser } = storeToRefs(store);
// Actions don't need storeToRefs
const { fetchUsers, setCurrentUser } = store;
onMounted(() => {
fetchUsers();
});
</script>
Router with TypeScript
Route Definitions
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router' ;
const routes : RouteRecordRaw [] = [
{
path : '/' ,
name : 'home' ,
component : () => import ('@/views/HomeView.vue' ),
},
{
path : '/users/:id' ,
name : 'user' ,
component : () => import ('@/views/UserView.vue' ),
props : true ,
},
{
path : '/admin' ,
name : 'admin' ,
component : () => import ('@/views/AdminView.vue' ),
meta : { requiresAuth : true },
},
];
export const router = createRouter ({
history : createWebHistory (),
routes,
});
Typed Route Params <script setup lang="ts">
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
// Typed param access
const userId = computed(() => route.params.id as string);
function goToUser(id: string) {
router.push({ name: 'user', params: { id } });
}
</script>
Form Handling
VeeValidate with Zod <script setup lang="ts">
import { useForm } from 'vee-validate';
import { toTypedSchema } from '@vee-validate/zod';
import { z } from 'zod';
const schema = toTypedSchema(
z.object({
email: z.string().email('Invalid email'),
password: z.string().min(8, 'Password must be at least 8 characters'),
})
);
const { handleSubmit, errors, defineField } = useForm({
validationSchema: schema,
});
const [email, emailAttrs] = defineField('email');
const [password, passwordAttrs] = defineField('password');
const onSubmit = handleSubmit((values) => {
console.log('Form submitted:', values);
});
</script>
<template>
<form @submit="onSubmit">
<input v-model="email" v-bind="emailAttrs" type="email" />
<span v-if="errors.email">{{ errors.email }}</span>
<input v-model="password" v-bind="passwordAttrs" type="password" />
<span v-if="errors.password">{{ errors.password }}</span>
<button type="submit">Submit</button>
</form>
</template>
Provide/Inject with TypeScript
import type { InjectionKey } from 'vue' ;
interface ThemeContext {
theme : Ref <'light' | 'dark' >;
toggleTheme : () => void ;
}
export const themeKey : InjectionKey <ThemeContext > = Symbol ('theme' );
const theme = ref<'light' | 'dark' >('light' );
const toggleTheme = ( ) => {
theme.value = theme.value === 'light' ? 'dark' : 'light' ;
};
provide (themeKey, { theme, toggleTheme });
const themeContext = inject (themeKey);
if (!themeContext) throw new Error ('Theme context not provided' );
Performance
Lazy Loading Components import { defineAsyncComponent } from 'vue' ;
const AsyncModal = defineAsyncComponent (() =>
import ('@/components/Modal.vue' )
);
const AsyncModalWithOptions = defineAsyncComponent ({
loader : () => import ('@/components/Modal.vue' ),
loadingComponent : LoadingSpinner ,
errorComponent : ErrorDisplay ,
delay : 200 ,
timeout : 3000 ,
});
File Structure src/
├── components/
│ ├── common/
│ │ ├── BaseButton.vue
│ │ └── BaseInput.vue
│ ├── layout/
│ │ ├── AppHeader.vue
│ │ └── AppSidebar.vue
│ └── features/
│ └── users/
├── composables/
│ ├── useAuth.ts
│ └── useFetch.ts
├── stores/
│ ├── userStore.ts
│ └── appStore.ts
├── views/
│ ├── HomeView.vue
│ └── UserView.vue
├── router/
│ └── index.ts
├── types/
│ └── index.ts
└── App.vue
Vue 3 + TypeScript patterns for modern frontend development