<script setup>
<script setup> 时,defineProps()
宏函数支持从它的参数中推导类型:<script setup lang="ts">
const props = defineProps({
foo: { type: String, required: true },
bar: Number
})
props.foo // string
props.bar // number | undefined
</script>
<script setup lang="ts">
const props = defineProps<{
foo: string
bar?: number
}>()
</script>
<script setup lang="ts">
interface Props {
foo: string
bar?: number
}
const props = defineProps<Props>()
</script>
<script setup lang="ts">
import type { Props } from './foo'
const props = defineProps<Props>()
</script>
</script>
export interface Props {
msg?: string
labels?: string[]
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two']
})
<script setup>
场景下<script setup>
,那么为了开启 props 的类型推导,必须使用 defineComponent()。传入 setup() 的 props 对象类型是从 props 选项中推导而来。import { defineComponent } from 'vue'
export default defineComponent({
props: {
message: String
},
setup(props) {
props.message // <-- 类型:string
}
})
<script setup lang="ts">
interface Book {
title: string
author: string
year: number
}
const props = defineProps<{
book: Book
}>()
</script>
import type { PropType } from 'vue'
const props = defineProps({
book: Object as PropType<Book>
})
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
export default defineComponent({
props: {
book: Object as PropType<Book>
}
})
<script setup>
中,emit 函数的类型标注也可以通过运行时声明或是类型声明进行:<script setup lang="ts">
// 运行时
const emit = defineEmits(['change', 'update'])
// 基于选项
const emit = defineEmits({
change: (id: number) => {
// 返回 `true` 或 `false`
// 表明验证通过或失败
},
update: (value: string) => {
// 返回 `true` 或 `false`
// 表明验证通过或失败
}
})
// 基于类型
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
// 3.3+: 可选的、更简洁的语法
const emit = defineEmits<{
change: [id: number]
update: [value: string]
}>()
</script>
<script setup>,defineComponent()
也可以根据 emits 选项推导暴露在 setup 上下文中的 emit 函数的类型:import { defineComponent } from 'vue'
export default defineComponent({
emits: ['change'],
setup(props, { emit }) {
emit('change') // <-- 类型检查 / 自动补全
}
})
import { ref } from 'vue'
// 推导出的类型:Ref<number>
const year = ref(2020)
// => TS Error: Type 'string' is not assignable to type 'number'.
year.value = '2020'
import { ref } from 'vue'
import type { Ref } from 'vue'
const year: Ref<string | number> = ref('2020')
year.value = 2020 // 成功!
// 得到的类型:Ref<string | number>
const year = ref<string | number>('2020')
year.value = 2020 // 成功!
// 推导得到的类型:Ref<number | undefined>
const n = ref<number>()
import { reactive } from 'vue'
// 推导得到的类型:{ title: string }
const book = reactive({ title: 'Vue 3 指引' })
import { reactive } from 'vue'
interface Book {
title: string
year?: number
}
const book: Book = reactive({ title: 'Vue 3 指引' })
import { ref, computed } from 'vue'
const count = ref(0)
// 推导得到的类型:ComputedRef<number>
const double = computed(() => count.value * 2)
// => TS Error: Property 'split' does not exist on type 'number'
const result = double.value.split('')
const double = computed<number>(() => {
// 若返回值不是 number 类型则会报错
})
<script setup lang="ts">
function handleChange(event) {
// `event` 隐式地标注为 `any` 类型
console.log(event.target.value)
}
</script>
<template>
<input type="text" @change="handleChange" />
</template>
function handleChange(event: Event) {
console.log((event.target as HTMLInputElement).value)
}
import { provide, inject } from 'vue'
import type { InjectionKey } from 'vue'
const key = Symbol() as InjectionKey<string>
provide(key, 'foo') // 若提供的是非字符串值会导致错误
const foo = inject(key) // foo 的类型:string | undefined
const foo = inject<string>('foo') // 类型:string | undefined
const foo = inject<string>('foo', 'bar') // 类型:string
const foo = inject('foo') as string
<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>
<!-- MyModal.vue -->
<script setup lang="ts">
import { ref } from 'vue'
const isContentShown = ref(false)
const open = () => (isContentShown.value = true)
defineExpose({
open
})
</script>
<!-- App.vue -->
<script setup lang="ts">
import MyModal from './MyModal.vue'
const modal = ref<InstanceType<typeof MyModal> | null>(null)
const openModal = () => {
modal.value?.open()
}
</script>
如果组件的具体类型无法获得,或者你并不关心组件的具体类型,那么可以使用 ComponentPublicInstance。这只会包含所有组件都共享的属性,比如 $el。
import { ref } from 'vue'
import type { ComponentPublicInstance } from 'vue'
const child = ref<ComponentPublicInstance | null>(null)