All skills
vuejs-ai avatar

/vue-debug-guides

@a5fc891 official
by Vue AIvuejs-ai/skills2.9k stars
167

Vue 3 debugging and error handling for runtime errors, warnings, async failures, and SSR/hydration issues. Use when diagnosing or fixing Vue issues.

Use this Skill: https://skilld.dev/gh/vuejs-ai/skills/vue-debug-guides

This session only. Nothing lands on disk.

referencets-defineprops-imported-types-limitations.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Imported Types Have Limitations in defineProps

Impact: MEDIUM - While Vue 3.3+ supports imported types in defineProps<>(), certain complex types are not fully supported. Conditional types, mapped types that require full type analysis, and global ambient types can cause "Unresolvable type reference" errors.

Task Checklist

  • Understand which type patterns are supported vs unsupported
  • Keep prop type definitions simple and explicit
  • Move complex type logic outside of defineProps
  • Export interfaces explicitly rather than using global declarations

Supported Patterns (Vue 3.3+)

// types/user.ts
export interface User {
  id: string
  name: string
  email?: string
}

export interface ListProps<T> {
  items: T[]
  selectedItem?: T
}

export type Status = 'pending' | 'active' | 'completed'
<script setup lang="ts">
import type { User, Status } from '@/types/user'

// WORKS: Simple imported interface
defineProps<{
  user: User
}>()

// WORKS: Imported union type
defineProps<{
  status: Status
}>()

// WORKS: Direct imported interface
defineProps<User>()
</script>

Unsupported Patterns

Conditional Types for Entire Props Object

// types/conditional.ts
export type ConditionalProps<T> = T extends string
  ? { value: string; onChange: (v: string) => void }
  : { value: number; onChange: (v: number) => void }
<script setup lang="ts">
import type { ConditionalProps } from '@/types/conditional'

// ERROR: Conditional types not supported for entire props object
defineProps<ConditionalProps<string>>()
</script>

Workaround:

<script setup lang="ts">
// Define the resolved type directly
interface StringProps {
  value: string
  onChange: (v: string) => void
}

defineProps<StringProps>()
</script>

Conditional Types for Individual Props ARE Supported

<script setup lang="ts">
// This WORKS - conditional type on individual prop
interface Props {
  value: SomeType extends string ? string : number  // OK
}

defineProps<Props>()
</script>

Global Ambient Types

// global.d.ts (ambient declaration without export)
interface GlobalUser {
  id: string
  name: string
}

// No export statement - this is an ambient declaration
<script setup lang="ts">
// ERROR: "Unresolvable type reference"
defineProps<{
  user: GlobalUser  // Can't resolve ambient global type
}>()
</script>

Workaround:

// types/user.ts - Use explicit export
export interface GlobalUser {
  id: string
  name: string
}
<script setup lang="ts">
import type { GlobalUser } from '@/types/user'

// WORKS: Explicitly imported
defineProps<{
  user: GlobalUser
}>()
</script>

Complex Mapped Types

// types/complex.ts
export type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
}

export interface User {
  id: string
  profile: { name: string }
}
<script setup lang="ts">
import type { DeepReadonly, User } from '@/types/complex'

// May fail or produce incorrect types
defineProps<{
  user: DeepReadonly<User>
}>()
</script>

Workaround:

// Resolve the type explicitly
export interface ReadonlyUser {
  readonly id: string
  readonly profile: { readonly name: string }
}

Union of Imported Interfaces

// types/forms.ts
export interface TextInput { type: 'text'; value: string }
export interface NumberInput { type: 'number'; value: number }
<script setup lang="ts">
import type { TextInput, NumberInput } from '@/types/forms'

// Can cause issues in some Vue versions
defineProps<{
  input: TextInput | NumberInput
}>()
</script>

Workaround:

// Define the union in the types file
export type AnyInput = TextInput | NumberInput
<script setup lang="ts">
import type { AnyInput } from '@/types/forms'

defineProps<{
  input: AnyInput
}>()
</script>

Best Practices

Keep Props Types Simple

// GOOD: Simple, explicit interface
export interface ButtonProps {
  variant: 'primary' | 'secondary' | 'danger'
  size: 'sm' | 'md' | 'lg'
  disabled?: boolean
  loading?: boolean
}

// AVOID: Over-engineered generic types
export type ButtonProps<V extends string, S extends string> = {
  variant: V
  size: S
  // ...complex type gymnastics
}

Resolve Types Before Export

// Instead of exporting generic utilities
// export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>

// Export the resolved type
export interface CreateUserProps {
  name: string
  email: string
  age?: number  // Made optional
  role?: 'admin' | 'user'  // Made optional
}

Use Dual Script Blocks for Complex Cases

<script lang="ts">
// Regular script block for complex type definitions
import type { ComplexType } from '@/types'

// Resolve the type here
type ResolvedProps = ComplexType extends SomeCondition
  ? { a: string }
  : { b: number }
</script>

<script setup lang="ts">
// Use the resolved type
defineProps<ResolvedProps>()
</script>

Version-Specific Behavior

Vue Version Imported Types Complex Types
3.2 Not supported Not supported
3.3 Supported Limited
3.4+ Supported Better support

Always check the Vue changelog for updates to type support in defineProps.

Reference

Source: SKILL.md on GitHub

1 warning17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill is a comprehensive collection of educational debugging guides and best practices for Vue 3 developers. It contains no executable code or malicious instructions and focuses solely on diagnosing common runtime errors and performance issues.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    140/140 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at a5fc891. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 8 months ago

README badge

README badge for vuejs-ai/skills/vue-debug-guides

Guides for diagnosing Vue 3 runtime errors, reactivity bugs, component lifecycle issues, and SSR hydration problems. Covers reactivity traps (refs, computed, watchers), component mechanics (props, emits, slots), templates (v-if, v-for, refs), forms (v-model), and composition API gotchas.

Generated from the current SKILL.md.

Does this cover Vue 2 or only Vue 3?
This skill is for Vue 3 only. It addresses Vue 3-specific debugging patterns like reactivity proxies, script setup, and defineEmits/defineProps.
Does this skill help with performance optimization?
No. This skill focuses on runtime errors, warnings, and behavioral bugs. For development best practices and optimization, use the separate `vue-best-practices` skill.
What kinds of issues does this cover?
Reactivity traps (refs, computed, watchers), component lifecycle bugs, template directives, form binding edge cases, SSR/hydration mismatches, slot scoping, and async-related failures.
Does this include debugging for Nuxt or other Vue frameworks?
No. This skill focuses on core Vue 3 runtime issues. Framework-specific bugs are outside its scope.

Generated from the current SKILL.md. These answers refresh after source changes.