Skip to content

Props/Emits Typing

11.2.1. defineProps Typing

Props must be typed using the generic syntax defineProps<T>(). The runtime declaration approach must not be used.

vue
<script setup lang="ts">
defineProps<{
  title: string
  count: number
  isActive: boolean
}>()
</script>

When props exceed 3 properties, extract them into a separate interface.

vue
<script setup lang="ts">
interface UserCardProps {
  userId: number
  name: string
  email: string
  role: string
  avatarUrl?: string
}

const props = defineProps<UserCardProps>()
</script>

11.2.2. withDefaults

Default values for props must use withDefaults. Default values for object or array types must use a factory function.

vue
<script setup lang="ts">
interface NotificationProps {
  message: string
  type?: 'info' | 'warning' | 'error'
  duration?: number
  actions?: string[]
}

const props = withDefaults(defineProps<NotificationProps>(), {
  type: 'info',
  duration: 3000,
  actions: () => [],
})
</script>
  • Primitive types (string, number, boolean) must have their values assigned directly.
  • Object and array types must use factory functions to prevent shared references across instances.

11.2.3. defineEmits Typing

Emits must define event signatures using the generic syntax. Payload types must be explicitly specified.

vue
<script setup lang="ts">
const emit = defineEmits<{
  search: [filters: { keyword: string; category: string }]
  reset: []
  select: [id: number, label: string]
}>()

function handleSearch(keyword: string, category: string) {
  emit('search', { keyword, category })
}
</script>
  • Events without a payload must be defined with an empty array [].
  • When a payload has 2 or more parameters, labels must be provided for readability.

11.2.4. Complex Props Patterns

Union Props are used to branch component behavior modes.

vue
<script setup lang="ts">
type ButtonProps =
  | { variant: 'link'; href: string; disabled?: boolean }
  | { variant: 'button'; onClick: () => void; disabled?: boolean }

const props = defineProps<ButtonProps>()
</script>

v-model Props must be defined as a modelValue and update:modelValue pair.

vue
<script setup lang="ts">
const props = defineProps<{ modelValue: string; placeholder?: string }>()
const emit = defineEmits<{ 'update:modelValue': [value: string] }>()
</script>

Conditionally required Props follow a pattern where different properties become required depending on a discriminant property.

vue
<script setup lang="ts">
type ModalProps =
  | { mode: 'confirm'; onConfirm: () => void; onCancel: () => void }
  | { mode: 'alert'; onConfirm: () => void }

const props = defineProps<ModalProps>()
</script>
  • When union Props become excessively complex, consider splitting into separate components.

TIENIPIA QUALIFIED STANDARD