Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3.5+ Composition API reference with progressive sub-file loading for components, composables, reactivity, and testing.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/typescript.md
1# Vue TypeScript Patterns23TypeScript-specific patterns for Vue 3 development.45## Provide/Inject Types67Use `InjectionKey` for type-safe dependency injection:89```ts10import type { InjectionKey } from 'vue'11import type { User } from './types'1213// Define typed key14export const UserKey: InjectionKey<User> = Symbol('user')1516// Provider component17const user = ref<User>({ id: 1, name: 'John' })18provide(UserKey, user)1920// Consumer component21const user = inject(UserKey) // Ref<User> | undefined22const user = inject(UserKey)! // Ref<User> (assert non-null)23```2425**With default value:**2627```ts28const user = inject(UserKey, ref({ id: 0, name: 'Guest' }))29// Type: Ref<User> (no undefined)30```3132## vue-tsc Strict Templates3334Enable stricter template type checking:3536```bash37# Check templates with strict mode38vue-tsc --noEmit --strict-templates39```4041Catches template errors like:4243- Accessing non-existent properties44- Wrong prop types45- Missing required props4647## tsconfig Settings4849**Required for Vue 3:**5051```json52{53"compilerOptions": {54"moduleResolution": "bundler",55"verbatimModuleSyntax": true,56"strict": true,57"jsx": "preserve"58}59}60```6162**`moduleResolution: "bundler"`** - Matches Vite/webpack resolution. Avoids `.js` extension issues.6364**`verbatimModuleSyntax: true`** - Enforces explicit `type` imports:6566```ts67// ❌ May cause issues with bundlers68import { User } from './types'6970// ✅ Explicit type import71import type { User } from './types'72```7374## Component Type Helpers7576**Extract props type from component:**7778```ts79import type { ComponentProps, ComponentSlots, ComponentEmits } from 'vue-component-type-helpers'80import MyComponent from './MyComponent.vue'8182type Props = ComponentProps<typeof MyComponent>83type Slots = ComponentSlots<typeof MyComponent>84type Emits = ComponentEmits<typeof MyComponent>85```8687**Extract exposed methods:**8889```ts90import type { ComponentExposed } from 'vue-component-type-helpers'9192type Exposed = ComponentExposed<typeof MyComponent>93```9495## Generic Components9697Define generic components with typed slots:9899```vue100<script setup lang="ts" generic="T extends { id: string }">101defineProps<{102items: T[]103}>()104105defineSlots<{106default: (props: { item: T }) => any107}>()108</script>109110<template>111<div v-for="item in items" :key="item.id">112<slot :item="item" />113</div>114</template>115```116117## Ref Type Narrowing118119Handle ref type narrowing correctly:120121```ts122const maybeUser = ref<User | null>(null)123124// ❌ TypeScript still sees User | null125if (maybeUser.value) {126maybeUser.value.name // Error: possibly null127}128129// ✅ Use computed or extract value130const userName = computed(() => maybeUser.value?.name ?? 'Guest')131132// ✅ Or guard in same expression133maybeUser.value && maybeUser.value.name134```135136## Event Handler Types137138Type event handlers correctly:139140```ts141// DOM events142const onClick = (e: MouseEvent) => { ... }143const onInput = (e: Event) => {144const target = e.target as HTMLInputElement145console.log(target.value)146}147148// Component emits149const onUpdate = (value: string) => { ... }150```151152## Common Mistakes153154**Forgetting to import types explicitly:**155156```ts157// ❌ Runtime import of type-only158import { User } from './types'159160// ✅ Type-only import161import type { User } from './types'162```163164**Not using `as const` for literal types:**165166```ts167// ❌ Type is string[]168const variants = ['primary', 'secondary']169170// ✅ Type is readonly ['primary', 'secondary']171const variants = ['primary', 'secondary'] as const172```173