TypeScript with Composition API â
āĻāĻ āĻĒā§āώā§āĻ āĻžāĻāĻŋ āϧāϰ⧠āύāĻŋāĻā§āĻā§ āϝ⧠āĻāĻĒāύāĻŋ āĻāϤāĻŋāĻŽāϧā§āϝā§āĻ Using Vue with TypeScript āĻāϰ āĻāĻāĻžāϰāĻāĻŋāĻāĻāĻŋ āĻĒāĻĄāĻŧā§āĻā§āύāĨ¤
Typing Component Props â
Using <script setup>
â
<script setup>
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, defineProps()
āĻŽā§āϝāĻžāĻā§āϰ⧠āϤāĻžāϰ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻāĻĒāϰ āĻāĻŋāϤā§āϤāĻŋ āĻāϰ⧠āĻĒā§āϰāĻĒ āϧāϰāύā§āϰ āĻ
āύā§āĻŽāĻžāύ āĻāϰāĻž āϏāĻŽāϰā§āĻĨāύ āĻāϰā§:
vue
<script setup lang="ts">
const props = defineProps({
foo: { type: String, required: true },
bar: Number
})
props.foo // string
props.bar // number | undefined
</script>
āĻāĻāĻŋāĻā§ "runtime declaration" āĻŦāϞāĻž āĻšāϝāĻŧ, āĻāĻžāϰāĻŖ defineProps()
-āĻ āĻĒāĻžāϏ āĻāϰāĻž āĻāϰā§āĻā§āĻŽā§āύā§āĻ āϰāĻžāύāĻāĻžāĻāĻŽ props
āĻŦāĻŋāĻāϞā§āĻĒ āĻšāĻŋāϏā§āĻŦā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāĻŦā§āĨ¤
āϝāĻžāĻāĻšā§āĻ, āϏāĻžāϧāĻžāϰāĻŖāϤ āĻāĻāĻāĻŋ āĻā§āύā§āϰāĻŋāĻ āĻāĻžāĻāĻĒ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻŦāĻŋāĻļā§āĻĻā§āϧ āĻĒā§āϰāĻāĻžāϰā§āϰ āϏāĻžāĻĨā§ āĻĒā§āϰāĻĒāϏāĻā§ āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āĻāϰāĻž āĻāϰāĻ āϏā§āĻāĻž:
vue
<script setup lang="ts">
const props = defineProps<{
foo: string
bar?: number
}>()
</script>
āĻāĻā§ "type-based declaration" āĻŦāϞāĻž āĻšāϝāĻŧāĨ¤ āĻāĻŽā§āĻĒāĻžāĻāϞāĻžāϰ āĻāĻžāĻāĻĒ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻāĻĒāϰ āĻāĻŋāϤā§āϤāĻŋ āĻāϰ⧠āϏāĻŽāϤā§āϞā§āϝ āϰāĻžāύāĻāĻžāĻāĻŽ āĻŦāĻŋāĻāϞā§āĻĒāĻā§āϞāĻŋ āĻ āύā§āĻŽāĻžāύ āĻāϰāĻžāϰ āĻāύā§āϝ āϝāĻĨāĻžāϏāĻžāϧā§āϝ āĻā§āώā§āĻāĻž āĻāϰāĻŦā§āĨ¤ āĻāĻ āĻā§āώā§āϤā§āϰā§, āĻāĻŽāĻžāĻĻā§āϰ āĻĻā§āĻŦāĻŋāϤā§āϝāĻŧ āĻāĻĻāĻžāĻšāϰāĻŖāĻāĻŋ āĻĒā§āϰāĻĨāĻŽ āĻāĻĻāĻžāĻšāϰāĻŖā§āϰ āĻŽāϤ⧠āĻāĻāĻ āϰāĻžāύāĻāĻžāĻāĻŽ āĻŦāĻŋāĻāϞā§āĻĒāĻā§āϞāĻŋāϤ⧠āĻāĻŽā§āĻĒāĻžāĻāϞ āĻāϰā§āĨ¤
āĻāĻĒāύāĻŋ type-based declaration āĻŦāĻž runtime declaration āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ, āĻāĻŋāύā§āϤ⧠āĻāĻĒāύāĻŋ āĻāĻāĻ āϏāĻŽāϝāĻŧā§ āĻāĻāϝāĻŧāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύ āύāĻžāĨ¤
āĻāĻŽāϰāĻž āĻāĻāĻāĻŋ āĻĒā§āĻĨāĻ āĻāύā§āĻāĻžāϰāĻĢā§āϏ⧠āĻĒā§āϰāĻĒāϏ āĻĒā§āϰāĻāĻžāϰāĻā§āϞāĻŋāĻā§ āϏā§āĻĨāĻžāύāĻžāύā§āϤāϰ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŋ:
vue
<script setup lang="ts">
interface Props {
foo: string
bar?: number
}
const props = defineProps<Props>()
</script>
āĻāĻāĻŋāĻ āĻāĻžāĻ āĻāϰ⧠āϝāĻĻāĻŋ Props
āĻā§āύ⧠āĻŦāĻžāĻšā§āϝāĻŋāĻ āĻā§āϏ āĻĨā§āĻā§ āĻāĻŽā§āĻĒā§āϰā§āĻ āĻāϰāĻž āĻšāϝāĻŧāĨ¤ āĻāĻ āĻŦā§āĻļāĻŋāώā§āĻā§āϝāĻāĻŋāϰ āĻāύā§āϝ Vue-āĻāϰ peer āύāĻŋāϰā§āĻāϰāϤāĻž āĻšāϤ⧠TypeScript āĻĒā§āϰāϝāĻŧā§āĻāύāĨ¤
vue
<script setup lang="ts">
import type { Props } from './foo'
const props = defineProps<Props>()
</script>
Syntax Limitations â
āϏāĻāϏā§āĻāϰāĻŖ 3.2 āĻāĻŦāĻ āύā§āĻā§, defineProps()
-āĻāϰ āĻāύā§āϝ āĻā§āύā§āϰāĻŋāĻ āĻāĻžāĻāĻĒ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāĻāĻžāϰ āĻāĻāĻāĻŋ āĻāĻā§āώāϰāĻŋāĻ āĻāĻžāĻāĻĒ āĻŦāĻž āϏā§āĻĨāĻžāύā§āϝāĻŧ āĻāύā§āĻāĻžāϰāĻĢā§āϏā§āϰ āĻāĻāĻāĻŋ āϰā§āĻĢāĻžāϰā§āύā§āϏā§āϰ āĻŽāϧā§āϝ⧠āϏā§āĻŽāĻžāĻŦāĻĻā§āϧ āĻāĻŋāϞāĨ¤
āĻāĻ āϏā§āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻž 3.3 āĻ āϏāĻŽāĻžāϧāĻžāύ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤ Vue-āĻāϰ āϏāϰā§āĻŦāĻļā§āώ āϏāĻāϏā§āĻāϰāĻŖāĻāĻŋ āĻāĻžāĻāĻĒ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāĻāĻžāϰ āĻ āĻŦāϏā§āĻĨāĻžāύ⧠āĻāĻŽāĻĻāĻžāύāĻŋ āĻāϰāĻž āϰā§āĻĢāĻžāϰā§āύā§āϏāĻŋāĻ āĻāĻŦāĻ āĻāĻāĻŋāϞ āϧāϰāύā§āϰ āĻāĻāĻāĻŋ āϏā§āĻŽāĻŋāϤ āϏā§āĻ āϏāĻŽāϰā§āĻĨāύ āĻāϰā§āĨ¤ āϝāĻžāĻāĻšā§āĻ, āϝā§āĻšā§āϤ⧠āϰāĻžāύāĻāĻžāĻāĻŽ āϰā§āĻĒāĻžāύā§āϤāϰā§āϰ āϧāϰāύāĻāĻŋ āĻāĻāύāĻ AST-āĻāĻŋāϤā§āϤāĻŋāĻ, āĻāĻŋāĻā§ āĻāĻāĻŋāϞ āĻĒā§āϰāĻāĻžāϰā§āϰ āĻĒā§āϰāĻā§āϤ āĻĒā§āϰāĻāĻžāϰ āĻŦāĻŋāĻļā§āϞā§āώāĻŖā§āϰ āĻĒā§āϰāϝāĻŧā§āĻāύ, āϝā§āĻŽāύ āĻļāϰā§āϤāĻžāϧā§āύ āĻĒā§āϰāĻāĻžāϰ, āϏāĻŽāϰā§āĻĨāĻŋāϤ āύāϝāĻŧāĨ¤ āĻāĻĒāύāĻŋ āĻāĻāĻāĻŋ āĻāĻāĻ āĻĒā§āϰāĻĒā§āϰ āϧāϰāĻŖā§āϰ āĻāύā§āϝ āĻļāϰā§āϤāϏāĻžāĻĒā§āĻā§āώ āĻĒā§āϰāĻāĻžāϰāĻā§āϞāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ, āϤāĻŦā§ āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻĒā§āϰāĻĒāϏ āĻ āĻŦāĻā§āĻā§āĻ āύāϝāĻŧāĨ¤
Props Default Values â
āĻāĻžāĻāĻĒ-āĻāĻŋāϤā§āϤāĻŋāĻ āĻā§āώāĻŖāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāĻŽāϰāĻž āĻĒā§āϰāĻĒāϏā§āϰ āĻāύā§āϝ āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύ āĻā§āώāĻŖāĻž āĻāϰāĻžāϰ āĻā§āώāĻŽāϤāĻž āĻšāĻžāϰāĻŋāϝāĻŧā§ āĻĢā§āϞāĻŋāĨ¤ Reactive Props Destructure āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāĻāĻŋ āϏāĻŽāĻžāϧāĻžāύ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
ts
interface Props {
msg?: string
labels?: string[]
}
const { msg = 'hello', labels = ['one', 'two'] } = defineProps<Props>()
In 3.4 and below, Reactive Props Destructure is not enabled by default. An alternative is to use the withDefaults
compiler macro:
ts
interface Props {
msg?: string
labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two']
})
āĻāĻāĻŋ āϏāĻŽāϤā§āϞā§āϝ āϰāĻžāύāĻāĻžāĻāĻŽ āĻĒā§āϰāĻĒāϏ default
āĻŦāĻŋāĻāϞā§āĻĒā§ āĻāĻŽā§āĻĒāĻžāĻāϞ āĻāϰāĻž āĻšāĻŦā§āĨ¤ āĻāĻĒāϰāύā§āϤā§, withDefaults
āĻšā§āϞā§āĻĒāĻžāϰ āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύāĻā§āϞāĻŋāϰ āĻāύā§āϝ āĻāĻžāĻāĻĒ āĻā§āĻ āĻĒā§āϰāĻĻāĻžāύ āĻāϰ⧠āĻāĻŦāĻ āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰ⧠āϝ⧠āĻĒā§āϰāϤā§āϝāĻžāĻŦāϰā§āϤāĻŋāϤ props
āĻāĻžāĻāĻĒāĻāĻŋāϤ⧠āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύ āĻā§āώāĻŋāϤ āĻŦā§āĻļāĻŋāώā§āĻā§āϝāĻā§āϞāĻŋāϰ āĻāύā§āϝ āĻāĻā§āĻāĻŋāĻ āĻĢā§āϞā§āϝāĻžāĻāĻā§āϞāĻŋ āϏāϰāĻžāύ⧠āĻšāϝāĻŧā§āĻā§āĨ¤
INFO
āĻŽāύ⧠āϰāĻžāĻāĻŦā§āύ āϝ⧠āĻĒāϰāĻŋāĻŦāϰā§āϤāύāϝā§āĻā§āϝ āϰā§āĻĢāĻžāϰā§āύā§āϏ āĻĒā§āϰāĻāĻžāϰā§āϰ (āϝā§āĻŽāύ āĻ
ā§āϝāĻžāϰ⧠āĻŦāĻž āĻ
āĻŦāĻā§āĻā§āĻ) āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύāĻā§āϞāĻŋ āĻĻā§āϰā§āĻāĻāύāĻžāĻāύāĻŋāϤ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāĻŦāĻ āĻŦāĻžāĻšā§āϝāĻŋāĻ āĻĒāĻžāϰā§āĻļā§āĻŦ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āĻāĻĄāĻŧāĻžāϤ⧠withDefaults
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻĢāĻžāĻāĻļāύ⧠āĻŽā§āĻĄāĻŧāĻžāύ⧠āĻāĻāĻŋāϤāĨ¤ āĻāĻāĻŋ āύāĻŋāĻļā§āĻāĻŋāϤ āĻāϰ⧠āϝ⧠āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻĻā§āώā§āĻāĻžāύā§āϤ āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύā§āϰ āύāĻŋāĻāϏā§āĻŦ āĻ
āύā§āϞāĻŋāĻĒāĻŋ āĻĒāĻžāϝāĻŧāĨ¤ āϧā§āĻŦāĻāϏā§āϰ āϏāĻžāĻĨā§ āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻāĻŋ āĻĒā§āϰāϝāĻŧā§āĻāύā§āϝāĻŧ āύāϝāĻŧāĨ¤
Without <script setup>
â
<script setup>
āĻŦā§āϝāĻŦāĻšāĻžāϰ āύāĻž āĻāϰāϞā§, āĻĒā§āϰāĻĒ āĻāĻžāĻāĻĒ āĻāύāĻĢāĻžāϰā§āύā§āϏ āϏāĻā§āώāĻŽ āĻāϰāϤ⧠defineComponent()
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻšāĻŦā§āĨ¤ āĻĒā§āϰāĻĒāϏ āĻ
āĻŦāĻā§āĻā§āĻā§āϰ āϧāϰāύ āϝāĻž setup()
-āĻ āĻĒāĻžāϏ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§ āϤāĻž props
āĻŦāĻŋāĻāϞā§āĻĒ āĻĨā§āĻā§ āĻ
āύā§āĻŽāĻžāύ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤
ts
import { defineComponent } from 'vue'
export default defineComponent({
props: {
message: String
},
setup(props) {
props.message // <-- type: string
}
})
Complex prop types â
āĻāĻžāĻāĻĒ-āĻāĻŋāϤā§āϤāĻŋāĻ āĻā§āώāĻŖāĻžāϰ āϏāĻžāĻĨā§, āĻāĻāĻāĻŋ āĻĒā§āϰāĻĒ āĻāĻāĻāĻŋ āĻāĻāĻŋāϞ āĻāĻžāĻāĻĒ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰ⧠āϝā§āĻŽāύ āĻ āύā§āϝ āϝā§āĻā§āύ⧠āϧāϰāύā§āϰ:
vue
<script setup lang="ts">
interface Book {
title: string
author: string
year: number
}
const props = defineProps<{
book: Book
}>()
</script>
For runtime declaration, āĻāĻŽāϰāĻž PropType
āĻāĻāĻāĻŋāϞāĻŋāĻāĻŋ āĻāĻžāĻāĻĒ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŋ:
ts
import type { PropType } from 'vue'
const props = defineProps({
book: Object as PropType<Book>
})
āĻāĻāĻŋ āĻāĻāĻāĻāĻžāĻŦā§ āĻāĻžāĻ āĻāϰ⧠āϝāĻĻāĻŋ āĻāĻŽāϰāĻž āϏāϰāĻžāϏāϰāĻŋ props
āĻŦāĻŋāĻāϞā§āĻĒāĻāĻŋ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāϰāĻāĻŋ:
ts
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
export default defineComponent({
props: {
book: Object as PropType<Book>
}
})
āĻ
āĻĒāĻļāύ āĻāĻĒāĻŋāĻāĻ-āĻāϰ āϏāĻžāĻĨā§ props
āĻŦāĻŋāĻāϞā§āĻĒāĻāĻŋ āĻŦā§āĻļāĻŋ āĻŦā§āϝāĻŦāĻšā§āϤ āĻšāϝāĻŧ, āϤāĻžāĻ āĻāĻĒāύāĻŋ TypeScript with Options API āĻāϰ āĻāĻžāĻāĻĄā§ āĻāϰāĻ āĻŦāĻŋāϏā§āϤāĻžāϰāĻŋāϤ āĻāĻĻāĻžāĻšāϰāĻŖ āĻĒāĻžāĻŦā§āύāĨ¤ āĻāĻ āĻāĻĻāĻžāĻšāϰāĻŖāĻā§āϞāĻŋāϤ⧠āĻĻā§āĻāĻžāύ⧠āĻā§āĻļāϞāĻā§āϞāĻŋ defineProps()
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āϰāĻžāύāĻāĻžāĻāĻŽ āĻā§āώāĻŖāĻžāϰ āĻā§āώā§āϤā§āϰā§āĻ āĻĒā§āϰāϝā§āĻā§āϝāĨ¤
Typing Component Emits â
<script setup>
-āĻ, emit
āĻĢāĻžāĻāĻļāύāĻāĻŋ āϰāĻžāύāĻāĻžāĻāĻŽ āĻā§āώāĻŖāĻž āĻŦāĻž āĻāĻžāĻāĻĒ āĻā§āώāĻŖāĻž āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āĻ āĻāĻžāĻāĻĒ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
vue
<script setup lang="ts">
// runtime
const emit = defineEmits(['change', 'update'])
// options based
const emit = defineEmits({
change: (id: number) => {
// return `true` or `false` to indicate
// validation pass / fail
},
update: (value: string) => {
// return `true` or `false` to indicate
// validation pass / fail
}
})
// type-based
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
// 3.3+: alternative, more succinct syntax
const emit = defineEmits<{
change: [id: number]
update: [value: string]
}>()
</script>
āĻāĻžāĻāĻĒ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤāĻā§āϞāĻŋāϰ āĻŽāϧā§āϝ⧠āĻāĻāĻāĻŋ āĻšāϤ⧠āĻĒāĻžāϰā§:
- āĻāĻāĻāĻŋ āĻāϞāϝā§āĻā§āϝ āĻĢāĻžāĻāĻļāύ āĻĒā§āϰāĻāĻžāϰ, āĻāĻŋāύā§āϤ⧠Call Signatures āϏāĻš āĻāĻā§āώāϰāĻŋāĻ āĻāĻžāĻāĻĒ āĻšāĻŋāϏāĻžāĻŦā§ āϞā§āĻāĻžāĨ¤ āĻāĻāĻŋ āϰāĻŋāĻāĻžāϰā§āύ āĻāϰāĻž
āĻemitāĻŽāĻŋāĻ
āĻĢāĻžāĻāĻļāύā§āϰ āϧāϰāĻŖ āĻšāĻŋāϏā§āĻŦā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāĻŦā§āĨ¤ - āĻāĻāĻāĻŋ āĻĒā§āϰāĻāĻžāϰ āĻāĻā§āώāϰāĻŋāĻ āϝā§āĻāĻžāύ⧠āĻā§āĻā§āϞāĻŋ āĻšāϞ āĻāĻā§āύā§āĻā§āϰ āύāĻžāĻŽ, āĻāĻŦāĻ āĻŽāĻžāύāĻā§āϞāĻŋ āĻšāϞ āĻ ā§āϝāĻžāϰā§/āĻā§āĻĒāϞ āĻĒā§āϰāĻāĻžāϰ āϝāĻž āĻāĻā§āύā§āĻā§āϰ āĻāύā§āϝ āĻ āϤāĻŋāϰāĻŋāĻā§āϤ āĻā§āĻšā§āϤ āĻĒāϰāĻžāĻŽāĻŋāϤāĻŋāĻā§āϞāĻŋāĻā§ āĻāĻĒāϏā§āĻĨāĻžāĻĒāύ āĻāϰā§āĨ¤ āĻāĻĒāϰā§āϰ āĻāĻĻāĻžāĻšāϰāĻŖāĻāĻŋ āύāĻžāĻŽāϝā§āĻā§āϤ tuples āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻā§ āϤāĻžāĻ āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻāĻāĻāĻŋ āϏā§āĻĒāώā§āĻ āύāĻžāĻŽ āĻĨāĻžāĻāϤ⧠āĻĒāĻžāϰā§āĨ¤
āĻāĻŽāϰāĻž āĻĻā§āĻāϤ⧠āĻĒāĻžāĻā§āĻāĻŋ, āĻāĻžāĻāĻĒ āĻĄāĻŋāĻā§āϞāĻžāϰā§āĻļāύ āĻāĻŽāĻžāĻĻā§āϰ āύāĻŋāϰā§āĻāϤ āĻāĻā§āύā§āĻā§āϰ āĻāĻžāĻāĻĒ āϏā§āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻžāϰ āĻāĻĒāϰ āĻ āύā§āĻ āϏā§āĻā§āώā§āĻŽ āύāĻŋāϝāĻŧāύā§āϤā§āϰāĻŖ āĻĻā§āϝāĻŧāĨ¤
<script setup>
āĻŦā§āϝāĻŦāĻšāĻžāϰ āύāĻž āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, defineComponent()
āϏā§āĻāĻāĻĒ āĻĒā§āϰāϏāĻā§āĻā§ āĻĒā§āϰāĻāĻžāĻļāĻŋāϤ emit
āĻĢāĻžāĻāĻļāύā§āϰ āĻāύā§āϝ āĻ
āύā§āĻŽā§āĻĻāĻŋāϤ āĻāĻā§āύā§āĻāĻā§āϞāĻŋ āĻ
āύā§āĻŽāĻžāύ āĻāϰāϤ⧠āϏāĻā§āώāĻŽ:
ts
import { defineComponent } from 'vue'
export default defineComponent({
emits: ['change'],
setup(props, { emit }) {
emit('change') // <-- type check / auto-completion
}
})
Typing ref()
â
Refs āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ āĻŽāĻžāύ āĻĨā§āĻā§ āĻĒā§āϰāĻāĻžāϰ āĻ āύā§āĻŽāĻžāύ āĻāϰā§:
ts
import { ref } from 'vue'
// inferred type: Ref<number>
const year = ref(2020)
// => TS Error: Type 'string' is not assignable to type 'number'.
year.value = '2020'
āĻāĻāύāĻ āĻāĻāύāĻ āĻāĻŽāĻžāĻĻā§āϰ āĻāĻāĻāĻŋ āϰā§āĻĢā§āϰ āĻ
āĻā§āϝāύā§āϤāϰā§āĻŖ āĻŽāĻžāύā§āϰ āĻāύā§āϝ āĻāĻāĻŋāϞ āĻĒā§āϰāĻāĻžāϰāĻā§āϞāĻŋ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāϰāϤ⧠āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤ āĻāĻŽāϰāĻž Ref
āĻāĻžāĻāĻĒ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāĻāĻŋ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŋ:
ts
import { ref } from 'vue'
import type { Ref } from 'vue'
const year: Ref<string | number> = ref('2020')
year.value = 2020 // ok!
āĻ
āĻĨāĻŦāĻž, āĻĄāĻŋāĻĢāϞā§āĻ āĻ
āύā§āĻŽāĻžāύāĻā§ āĻāĻāĻžāϰāϰāĻžāĻāĻĄ āĻāϰāϤ⧠ref()
āĻāϞ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻāĻāĻŋ āĻā§āύā§āϰāĻŋāĻ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻĒāĻžāϏ āĻāϰā§:
ts
// resulting type: Ref<string | number>
const year = ref<string | number>('2020')
year.value = 2020 // ok!
āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻāĻāĻāĻŋ āĻā§āύā§āϰāĻŋāĻ āĻāĻžāĻāĻĒ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāϰā§āύ āĻāĻŋāύā§āϤ⧠āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ āĻŽāĻžāύāĻāĻŋ āĻŦāĻžāĻĻ āĻĻā§āύ, āϤāĻžāĻšāϞ⧠āĻĢāϞāĻžāĻĢāϞā§āϰ āϧāϰāύāĻāĻŋ āĻšāĻŦā§ āĻāĻāĻāĻŋ āĻāĻāύāĻŋāϝāĻŧāύā§āϰ āϧāϰāύ āϝāĻžāϤ⧠undefined
āĻ
āύā§āϤāϰā§āĻā§āĻā§āϤ āĻĨāĻžāĻā§:
ts
// inferred type: Ref<number | undefined>
const n = ref<number>()
Typing reactive()
â
reactive()
āĻāĻāĻžāĻĄāĻŧāĻžāĻ āĻāϰ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻĨā§āĻā§ āĻāĻžāĻāĻĒāĻāĻŋāĻā§ āĻ
āύā§āϤāϰā§āύāĻŋāĻšāĻŋāϤāĻāĻžāĻŦā§ āĻ
āύā§āĻŽāĻžāύ āĻāϰā§:
ts
import { reactive } from 'vue'
// inferred type: { title: string }
const book = reactive({ title: 'Vue 3 Guide' })
āϏā§āĻĒāώā§āĻāĻāĻžāĻŦā§ āĻāĻāĻāĻŋ reactive
āĻŦā§āĻļāĻŋāώā§āĻā§āϝ āĻāĻžāĻāĻĒ āĻāϰāϤā§, āĻāĻŽāϰāĻž āĻāύā§āĻāĻžāϰāĻĢā§āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŋ:
ts
import { reactive } from 'vue'
interface Book {
title: string
year?: number
}
const book: Book = reactive({ title: 'Vue 3 Guide' })
TIP
āĻāĻāĻŋ reactive()
āĻāϰ āĻā§āύā§āϰāĻŋāĻ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āĻĒāϰāĻžāĻŽāϰā§āĻļ āĻĻā§āĻāϝāĻŧāĻž āĻšāϝāĻŧ āύāĻž āĻāĻžāϰāĻŖ āϰāĻŋāĻāĻžāϰā§āύ āĻāϰāĻž āĻāĻžāĻāĻĒ, āϝāĻž āύā§āϏā§āĻā§āĻĄ āϰā§āĻĢ āĻāύāϰā§āϝāĻžāĻĒāĻŋāĻ āĻĒāϰāĻŋāĻāĻžāϞāύāĻž āĻāϰā§, āĻā§āύā§āϰāĻŋāĻ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻāĻžāĻāĻĒ āĻĨā§āĻā§ āĻāϞāĻžāĻĻāĻžāĨ¤
Typing computed()
â
āĻĒā§āϰāĻžāĻĒā§āϤāĻŋāϰ āϰāĻŋāĻāĻžāϰā§āύ āĻŽāĻžāύā§āϰ āĻāĻĒāϰ āĻāĻŋāϤā§āϤāĻŋ āĻāϰ⧠computed()
āĻāϰ āϧāϰāύ āĻ
āύā§āĻŽāĻžāύ āĻāϰā§:
ts
import { ref, computed } from 'vue'
const count = ref(0)
// inferred type: ComputedRef<number>
const double = computed(() => count.value * 2)
// => TS Error: Property 'split' does not exist on type 'number'
const result = double.value.split('')
āĻāĻĒāύāĻŋ āĻāĻāĻāĻŋ āĻā§āύā§āϰāĻŋāĻ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻāĻāĻāĻŋ āϏā§āĻĒāώā§āĻ āĻĒā§āϰāĻāĻžāϰ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ:
ts
const double = computed<number>(() => {
// type error if this doesn't return a number
})
Typing Event Handlers â
āύā§āĻāĻŋāĻ DOM āĻāĻā§āύā§āĻāĻā§āϞāĻŋāϰ āϏāĻžāĻĨā§ āĻĄāĻŋāϞ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāĻŽāϰāĻž āĻšā§āϝāĻžāύā§āĻĄāϞāĻžāϰāĻā§ āϏāĻ āĻŋāĻāĻāĻžāĻŦā§ āϝ⧠āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻĻāĻŋāϝāĻŧā§ āĻĨāĻžāĻāĻŋ āϤāĻž āĻāĻžāĻāĻĒ āĻāϰāĻž āĻāĻžāϰā§āϝāĻāϰ āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤ āĻāϏā§āύ āĻāĻ āĻāĻĻāĻžāĻšāϰāĻŖāĻāĻŋ āĻāĻāĻŦāĻžāϰ āĻĻā§āĻā§ āύā§āĻāϝāĻŧāĻž āϝāĻžāĻ:
vue
<script setup lang="ts">
function handleChange(event) {
// `event` implicitly has `any` type
console.log(event.target.value)
}
</script>
<template>
<input type="text" @change="handleChange" />
</template>
āĻāĻžāĻāĻĒ āĻā§āĻāĻž āĻŦā§āϝāϤā§āϤ, event
āĻāϰā§āĻā§āĻŽā§āύā§āĻā§ āύāĻŋāĻšāĻŋāϤāĻāĻžāĻŦā§ any
āĻĒā§āϰāĻāĻžāϰ āĻĨāĻžāĻāĻŦā§āĨ¤ tsconfig.json
-āĻ āϝāĻĻāĻŋ "strict": true
āĻŦāĻž "noImplicitAny": true
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧ āϤāĻžāĻšāϞ⧠āĻāĻāĻŋ āĻāĻāĻāĻŋ TS āϤā§āϰā§āĻāĻŋāϰ āĻāĻžāϰāĻŖ āĻšāĻŦā§āĨ¤ āϤāĻžāĻ āĻāĻā§āύā§āĻ āĻšā§āϝāĻžāύā§āĻĄāϞāĻžāϰāĻĻā§āϰ āϝā§āĻā§āϤāĻŋ āϏā§āĻĒāώā§āĻāĻāĻžāĻŦā§ āĻā§āĻāĻž āĻāϰāĻžāϰ āϏā§āĻĒāĻžāϰāĻŋāĻļ āĻāϰāĻž āĻšāϝāĻŧāĨ¤ āĻāĻĒāϰāύā§āϤā§, event
āĻāϰ āĻŦā§āĻļāĻŋāώā§āĻā§āϝāĻā§āϞāĻŋ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻĒāύāĻžāĻā§ āĻāĻžāĻāĻĒ āĻ
ā§āϝāĻžāϏāĻžāϰā§āĻā§āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻšāϤ⧠āĻĒāĻžāϰā§:
ts
function handleChange(event: Event) {
console.log((event.target as HTMLInputElement).value)
}
Typing Provide / Inject â
āĻĒā§āϰāĻĻāĻžāύ āĻāĻŦāĻ āĻāύāĻā§āĻāĻļāύ āϏāĻžāϧāĻžāϰāĻŖāϤ āĻĒā§āĻĨāĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āϏāĻā§āĻāĻžāϞāĻŋāϤ āĻšāϝāĻŧ. āϏāĻ āĻŋāĻāĻāĻžāĻŦā§ āĻāύāĻā§āĻāĻļāύ āĻāϰāĻž āĻŽāĻžāύ āĻāĻžāĻāĻĒ āĻāϰāϤā§, Vue āĻāĻāĻāĻŋ InjectionKey
āĻāύā§āĻāĻžāϰāĻĢā§āϏ āĻĒā§āϰāĻĻāĻžāύ āĻāϰā§, āϝāĻž āĻāĻāĻāĻŋ āĻā§āύā§āϰāĻŋāĻ āĻāĻžāĻāĻĒ āϝāĻž Symbol
āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻāϰā§āĨ¤ āĻāĻāĻŋ āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰ⧠āĻāĻŦāĻ āĻā§āĻā§āϤāĻžāϰ āĻŽāϧā§āϝ⧠āĻāύāĻā§āĻāĻļāύā§āϰ āĻŽāĻžāύāĻāĻŋāϰ āϧāϰāύ āϏāĻŋāĻā§āĻ āĻāϰāϤ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
ts
import { provide, inject } from 'vue'
import type { InjectionKey } from 'vue'
const key = Symbol() as InjectionKey<string>
provide(key, 'foo') // providing non-string value will result in error
const foo = inject(key) // type of foo: string | undefined
āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻĒā§āĻĨāĻ āĻĢāĻžāĻāϞ⧠āĻāύāĻā§āĻāĻļāύ āĻā§ āϰāĻžāĻāĻžāϰ āϏā§āĻĒāĻžāϰāĻŋāĻļ āĻāϰāĻž āĻšāϝāĻŧ āϝāĻžāϤ⧠āĻāĻāĻŋ āĻāĻāĻžāϧāĻŋāĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§ āĻāĻŽāĻĻāĻžāύāĻŋ āĻāϰāĻž āϝāĻžāϝāĻŧāĨ¤
āϏā§āĻā§āϰāĻŋāĻ āĻāύāĻā§āĻāĻļāύ āĻā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāύāĻā§āĻāĻļāύā§āϰ āĻŽāĻžāύāĻāĻŋāϰ āϧāϰāύ āĻšāĻŦā§ unknown
, āĻāĻŦāĻ āĻāĻāĻāĻŋ āĻā§āύā§āϰāĻŋāĻ āĻāĻžāĻāĻĒ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻŽāĻžāϧā§āϝāĻŽā§ āϏā§āĻĒāώā§āĻāĻāĻžāĻŦā§ āĻā§āώāĻŖāĻž āĻāϰāĻž āĻĒā§āϰāϝāĻŧā§āĻāύ:
ts
const foo = inject<string>('foo') // type: string | undefined
āϞāĻā§āώā§āϝ āĻāϰā§āύ āĻāύāĻā§āĻāĻļāύā§āϰ āĻŽāĻžāύāĻāĻŋ āĻāĻāύāĻ undefined
āĻšāϤ⧠āĻĒāĻžāϰā§, āĻāĻžāϰāĻŖ āϰāĻžāύāĻāĻžāĻāĻŽā§ āĻā§āύ⧠āĻĒā§āϰāĻĻāĻžāύāĻāĻžāϰ⧠āĻāĻ āĻŽāĻžāύāĻāĻŋ āĻĒā§āϰāĻĻāĻžāύ āĻāϰāĻŦā§ āĻāĻŽāύ āĻā§āύ⧠āĻā§āϝāĻžāϰāĻžāύā§āĻāĻŋ āύā§āĻāĨ¤
āĻāĻāĻāĻŋ āĻĄāĻŋāĻĢāϞā§āĻ āĻŽāĻžāύ āĻĒā§āϰāĻĻāĻžāύ āĻāϰ⧠undefined
āĻĒā§āϰāĻāĻžāϰāĻāĻŋ āϏāϰāĻžāύ⧠āϝā§āϤ⧠āĻĒāĻžāϰā§:
ts
const foo = inject<string>('foo', 'bar') // type: string
āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ āύāĻŋāĻļā§āĻāĻŋāϤ āĻšāύ āϝ⧠āĻŽāĻžāύāĻāĻŋ āϏāϰā§āĻŦāĻĻāĻž āĻĒā§āϰāĻĻāĻžāύ āĻāϰāĻž āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧠āĻāĻĒāύāĻŋ āĻŽāĻžāύāĻāĻŋ āĻā§āϰ āĻāϰ⧠āύāĻŋāĻā§āώā§āĻĒ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ:
ts
const foo = inject('foo') as string
Typing Template Refs â
Vue 3.5 āĻāĻŦāĻ @vue/language-tools
2.1 (IDE āĻāĻžāώāĻž āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāĻŦāĻ vue-tsc
āĻāĻāϝāĻŧāĻā§āĻ āĻļāĻā§āϤāĻŋ āĻĻā§āϝāĻŧ), SFC-āϤ⧠useTemplateRef()
āĻĻā§āĻŦāĻžāϰāĻž āϤā§āϰāĻŋ āϰā§āĻĢā§āϰ āϧāϰāύ āϏā§āĻŦāϝāĻŧāĻāĻā§āϰāĻŋāϝāĻŧāĻāĻžāĻŦā§ āĻ
āύā§āĻŽāĻžāύ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰ⧠āϏā§āĻā§āϝāĻžāĻāĻŋāĻ refs āĻā§āύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§ āĻŽāĻŋāϞāĻŋāϤ āϰā§āĻĢ
āĻ
ā§āϝāĻžāĻā§āϰāĻŋāĻŦāĻŋāĻāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§ āϤāĻžāϰ āĻāĻĒāϰ āĻāĻŋāϤā§āϤāĻŋ āĻāϰā§āĨ¤
āϝ⧠āĻā§āώā§āϤā§āϰ⧠āϏā§āĻŦāϝāĻŧāĻ-āĻ āύā§āĻŽāĻžāύ āĻāϰāĻž āϏāĻŽā§āĻāĻŦ āύāϝāĻŧ, āĻāĻĒāύāĻŋ āĻāĻāύāĻ āĻā§āύā§āϰāĻŋāĻ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻā§āĻŽāĻĒā§āϞā§āĻ āϰā§āĻĢāĻāĻŋāĻā§ āĻāĻāĻāĻŋ āϏā§āϏā§āĻĒāώā§āĻ āĻĒā§āϰāĻāĻžāϰ⧠āĻāĻžāϏā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ:
ts
const el = useTemplateRef<HTMLInputElement>('el')
ā§Š.ā§Ģ āĻāϰ āĻāĻā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ
āĻā§āĻŽāĻĒā§āϞā§āĻ āϰā§āĻĢ āĻāĻāĻāĻŋ āϏā§āĻĒāώā§āĻ āĻā§āύā§āϰāĻŋāĻ āĻāĻžāĻāĻĒ āĻāϰā§āĻā§āĻŽā§āύā§āĻ āĻāĻŦāĻ 'āύāĻžāϞ' āĻāϰ āĻāĻāĻāĻŋ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ āĻŽāĻžāύ āĻĻāĻŋāϝāĻŧā§ āϤā§āϰāĻŋ āĻāϰāĻž āĻāĻāĻŋāϤ:
vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const el = ref<HTMLInputElement | null>(null)
onMounted(() => {
el.value?.focus()
})
</script>
<template>
<input ref="el" />
</template>
āϏāĻ āĻŋāĻ DOM āĻāύā§āĻāĻžāϰāĻĢā§āϏ āĻĒā§āϤ⧠āĻāĻĒāύāĻŋ MDN āĻāϰ āĻŽāϤ⧠āĻĒā§āώā§āĻ āĻžāĻā§āϞāĻŋ āĻĒāϰā§āĻā§āώāĻž āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āĻŽāύ⧠āϰāĻžāĻāĻŦā§āύ āϝ⧠āĻāĻ ā§āϰ āϧāϰāύā§āϰ āύāĻŋāϰāĻžāĻĒāϤā§āϤāĻžāϰ āĻāύā§āϝ, el.value
āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻā§āĻāĻŋāĻ āĻā§āĻāύāĻŋāĻ āĻŦāĻž āĻāĻžāĻāĻĒ āĻāĻžāϰā§āĻĄ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻĒā§āϰāϝāĻŧā§āĻāύāĨ¤ āĻāĻžāϰāĻŖ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻŽāĻžāĻāύā§āĻ āύāĻž āĻšāĻāϝāĻŧāĻž āĻĒāϰā§āϝāύā§āϤ āϰā§āĻĢ āĻāϰ āĻŽāĻžāύ null
āĻĨāĻžāĻā§ āĻāĻŦāĻ āϝāĻĻāĻŋ āϰā§āĻĢāĻžāϰā§āύā§āϏāĻā§āϤ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ v-if
āĻĻā§āĻŦāĻžāϰāĻž āĻāύāĻŽāĻžāĻāύā§āĻ āĻāϰāĻž āĻšāϝāĻŧ āϤāĻžāĻšāϞ⧠āĻāĻāĻŋ null
āϏā§āĻ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§āĨ¤
Typing Component Template Refs â
Vue 3.5 āĻāĻŦāĻ @vue/language-tools
2.1 (IDE āĻāĻžāώāĻž āĻĒāϰāĻŋāώā§āĻŦāĻž āĻāĻŦāĻ vue-tsc
āĻāĻāϝāĻŧāĻā§āĻ āĻļāĻā§āϤāĻŋ āĻĻā§āϝāĻŧ), SFC-āϤ⧠useTemplateRef()
āĻĻā§āĻŦāĻžāϰāĻž āϤā§āϰāĻŋ āϰā§āĻĢā§āϰ āϧāϰāύ āϏā§āĻŦāϝāĻŧāĻāĻā§āϰāĻŋāϝāĻŧāĻāĻžāĻŦā§ āĻ
āύā§āĻŽāĻžāύ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰ⧠āϏā§āĻā§āϝāĻžāĻāĻŋāĻ āϰā§āĻĢā§āϰ āĻāĻĒāϰ āĻāĻŋāϤā§āϤāĻŋ āĻāϰ⧠āĻā§āύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻŦāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āϏāĻžāĻĨā§ āĻŽāĻŋāϞ⧠āϝāĻžāĻāϝāĻŧāĻž āϰā§āĻĢ
āĻ
ā§āϝāĻžāĻā§āϰāĻŋāĻŦāĻŋāĻāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤
āϝā§āϏāĻŦ āĻā§āώā§āϤā§āϰ⧠āϏā§āĻŦāϝāĻŧāĻ-āĻ āύā§āĻŽāĻžāύ āĻāϰāĻž āϏāĻŽā§āĻāĻŦ āύāϝāĻŧ (āϝā§āĻŽāύ āύāύ-āĻāϏāĻāĻĢāϏāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻŦāĻž āĻāϤāĻŋāĻļā§āϞ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ), āĻāĻĒāύāĻŋ āĻāĻāύāĻ āĻā§āύā§āϰāĻŋāĻ āĻāϰā§āĻā§āĻŽā§āύā§āĻā§āϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻā§āĻŽāĻĒā§āϞā§āĻ āϰā§āĻĢāĻā§ āĻāĻāĻāĻŋ āϏā§āϏā§āĻĒāώā§āĻ āĻĒā§āϰāĻāĻžāϰ⧠āĻāĻžāϏā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āĻāĻāĻāĻŋ āĻāĻŽā§āĻĒā§āϰā§āĻ āĻāϰāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āĻāύāϏā§āĻā§āϝāĻžāύā§āϏ āĻāĻžāĻāĻĒ āĻĒā§āϤā§, āĻāĻŽāĻžāĻĻā§āϰ āĻĒā§āϰāĻĨāĻŽā§ typeof
āĻāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻāϰ āĻāĻžāĻāĻĒ āĻĒā§āϤ⧠āĻšāĻŦā§, āϤāĻžāϰāĻĒāϰ TypeScript āĻāϰ āĻ
āύā§āϤāϰā§āύāĻŋāϰā§āĻŽāĻŋāϤ InstanceType
āĻāĻāĻāĻŋāϞāĻŋāĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāϰ āĻāύāϏā§āĻā§āϝāĻžāύā§āϏ āĻāĻžāĻāĻĒ āĻŦā§āϰ āĻāϰāϤ⧠āĻšāĻŦā§:
vue
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
type FooType = InstanceType<typeof Foo>
type BarType = InstanceType<typeof Bar>
const compRef = useTemplateRef<FooType | BarType>('comp')
</script>
<template>
<component :is="Math.random() > 0.5 ? Foo : Bar" ref="comp" />
</template>
āϝ⧠āĻā§āώā§āϤā§āϰ⧠āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āϏāĻ āĻŋāĻ āϧāϰāύ āĻĒāĻžāĻāϝāĻŧāĻž āϝāĻžāϝāĻŧ āύāĻž āĻŦāĻž āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖ āύāϝāĻŧ, āϤāĻžāϰ āĻĒāϰāĻŋāĻŦāϰā§āϤ⧠ComponentPublicInstance
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§āĨ¤ āĻāĻāĻŋ āĻā§āĻŦāϞāĻŽāĻžāϤā§āϰ āϏā§āĻ āĻŦā§āĻļāĻŋāώā§āĻā§āϝāĻā§āϞāĻŋ āĻ
āύā§āϤāϰā§āĻā§āĻā§āϤ āĻāϰāĻŦā§ āϝāĻž āϏāĻŽāϏā§āϤ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻĻā§āĻŦāĻžāϰāĻž āĻāĻžāĻ āĻāϰāĻž āĻšāϝāĻŧ, āϝā§āĻŽāύ $el
:
ts
import { useTemplateRef } from 'vue'
import type { ComponentPublicInstance } from 'vue'
const child = useTemplateRef<ComponentPublicInstance>('child')
āĻāϞā§āϞā§āĻ āĻāϰāĻž āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻā§āύā§āϰāĻŋāĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ, āĻāĻĻāĻžāĻšāϰāĻŖāϏā§āĻŦāϰā§āĻĒ MyGenericModal
:
vue
<script setup lang="ts" generic="ContentType extends string | number">
import { ref } from 'vue'
const content = ref<ContentType | null>(null)
const open = (newContent: ContentType) => (content.value = newContent)
defineExpose({
open
})
</script>
āĻāĻāĻŋāĻā§ vue-component-type-helpers
āϞāĻžāĻāĻŦā§āϰā§āϰāĻŋ āĻĨā§āĻā§ ComponentExposed
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāϞā§āϞā§āĻ āĻāϰāĻž āĻĻāϰāĻāĻžāϰ āĻāĻžāϰāĻŖ InstanceType
āĻāĻžāĻ āĻāϰāĻŦā§ āύāĻžāĨ¤
vue
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import MyGenericModal from './MyGenericModal.vue'
import type { ComponentExposed } from 'vue-component-type-helpers'
const modal = useTemplateRef<ComponentExposed<typeof MyGenericModal>>('modal')
const openModal = () => {
modal.value?.open('newValue')
}
</script>
Note that with @vue/language-tools
2.1+, static template refs' types can be automatically inferred and the above is only needed in edge cases.
GitHub-āĻ āĻāĻ āĻĒā§āώā§āĻ āĻžāĻāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ