Vue3 + tsx 如何定义作用域插槽参数的类型?

在 vue3 + ts 中假设我需要一个作用域插槽,并且需要传递一些参数,当使用模版语法时,可以得到正确的ts类型提示。

<script lang="ts" setup>
import { ref } from 'vue';

  const data = ref('data')
  const content = ref('content')
</script>

<template>
  <div>
    ScopedSlots
    <slot name="content" :data="data" :content="content" />
  </div>
</template>
<script setup lang="ts">
import ScopedSlots from '@/components/ScopedSlots.vue';
import ScopedSlotsTSX from '@/components/ScopedSlotsTSX';

</script>

<template>
  <main>
    HomeView

    <ScopedSlots>
      <!-- 
        可以得到正确的类型提示
        (property) content: {
          data: string;
          content: string;
        } 
      -->
      <template #content="{ data, content }">
        {{ data }} {{ content }}
      </template>
    </ScopedSlots>
  </main>
</template>

但是使用 tsx 语法时,以下的写法不能正确的得到类型提示(content 提示为 any):

import { defineComponent, ref } from "vue";

export default defineComponent({
    setup (props, { slots }) {
        const content = ref("content")
        const data = ref("data")

        return function render () {
            return (
                <div>
                    ScopedSlotsTSX

                    { slots.content ? slots.content({ data, content }) : null }
                </div>
            )
        }
    }
})
<script setup lang="ts">
import ScopedSlots from '@/components/ScopedSlots.vue';
import ScopedSlotsTSX from '@/components/ScopedSlotsTSX';

</script>

<template>
  <main>
    HomeView

    <ScopedSlotsTSX>
      <!-- content 类型显示为 any -->
      <template #content="data">
        {{ data }}
      </template>
    </ScopedSlotsTSX>
  </main>
</template>

想问下,使用 tsx 时,如何定义作用域插槽传递的参数的类型?

下面是在线预览地址 codesandbox

阅读 7.4k
2 个回答

vue 官方暂时不支持定义插槽的类型,但是有相关的 rfc

2023-05-11更新:

3.3.0版本后支持使用 defineSlots 和 slots 来设置插槽的类型:
Support imported types in SFC macros

Setup SFC:

<script setup lang="ts">
const slots = defineSlots<{
  default(props: { foo: string; bar: number }): any // or VNode[]
}>()
</script>

Options Api:

import { SlotsType } from 'vue'

defineComponent({
  slots: Object as SlotsType<{
    default: { foo: string; bar: number }
    item: { data: number }
  }>,
  setup(props, { slots }) {
    expectType<undefined | ((scope: { foo: string; bar: number }) => any)>(
      slots.default
    )
    expectType<undefined | ((scope: { data: number }) => any)>(slots.item)
  }
})
新手上路,请多包涵

不知道楼主最终有没有找到解决方案

我找了一圈只找到了如何在 tsx 中定义插槽的类型,其实用的是选项式API

image.png

但这样,在引用这个组件处,还是不能得到插槽的类型提示,我只好在使用处加了类型推导。用 ts 的初衷更多的是类型定义,这样至少能够解决拿不到类型定义的问题,尽管不是很优雅

image.png

推荐问题
logo
Microsoft
子站问答
访问
宣传栏