defineProps/defineEmits Get Generic
TypeScript in Vue
Generic forms of the script-setup macros give full TS inference for props and emits — no runtime declarations, full type-checking in templates with Volar.
What you'll learn
- Use defineProps with a type literal
- Use defineEmits with named events and tuples
- Type refs explicitly where inference fails
Vue’s <script setup> macros each have a generic form that lets you describe shapes purely in TypeScript — no runtime objects, no manual PropType casts.
Typed Props
Pass an interface or inline type literal to defineProps.
<script setup lang="ts">
interface Props {
name: string
age?: number
tags?: string[]
}
const props = defineProps<Props>()
</script> Defaults for optional props need withDefaults:
<script setup lang="ts">
const props = withDefaults(defineProps<Props>(), {
age: 0,
tags: () => [],
})
</script> Typed Emits
Tuple syntax — each event maps to the args it carries.
const emit = defineEmits<{
save: [user: User]
cancel: []
'page-change': [page: number]
}>()
emit('save', { id: 1, name: 'Ada' }) Typed Refs
ref() infers, but for “starts null, gets set later” you’ll want an explicit generic.
import { ref } from 'vue'
const name = ref<string>('') // string
const user = ref<User | null>(null) // tagged union
const list = ref<User[]>([]) // generic array Template Refs
Component refs need the typeof the component for full IntelliSense.
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import MyInput from './MyInput.vue'
const inputRef = useTemplateRef<InstanceType<typeof MyInput>>('input')
</script> Volar
Install the Vue (Official) extension for VS Code (a.k.a. Volar). It type-checks templates — wrong prop names and missing emits show up as errors in your editor.
Internationalization With vue-i18n →