typescript 在使用vue3和tsx时,是否有一种方法来定义泛型props

yyhrrdl8  于 2023-05-23  发布在  TypeScript
关注(0)|答案(1)|浏览(297)

当我们处于功能模式时,我们有一个简单的方法来定义通用vue组件:

type Loading = { status: 'LOADING' }
type Error = { status: 'ERROR'; message: string }
type AsyncData<T> = Loading | { status: 'LOADED'; value: T } | Error

type Props<T> = {
  data: AsyncData<T>
  renderItem: (item: T) => JSX.Element | null
}

const LoadingElement = <T,>(props: Props<T>) => {
  return (
    <div class={`${props.data.status === 'LOADING' ? styles['top-level'] : ''}`} style={props.data.status !== 'LOADED' ? 'display: flex; justify-content: center' : ''}>
      {props.data.status === 'LOADED' ? props.renderItem(props.data.value) : null}
      {props.data.status === 'ERROR' ? (
        <div>
          <HelpTooltip icon="error-warning" text={props.data.message} />
        </div>
      ) : null}
      {props.data.status === 'LOADING' ? <div class={styles.spinner}></div> : null}
    </div>
  )
}

我可以这样使用:

<LoadingElement data={utilisateur.value} renderItem={item => <>{item ? `${item.prenom || '–'} ${item.nom || '–'}` : '–'}</>} />

其中项被正确键入。
我的主要问题是使用defineComponent(即。当我需要使用ref、watch或computed时,...)我无法找到正确泛化组件的方法。
最糟糕的是将我们的组件 Package 在一个功能组件中。
例如:

const GenericComponentHack = <T>() =>
  defineComponent<Props<T>>({ setup(props) => {
    return () => <OtherComponent {...props} />
  })

export const GenericComponent = <T>(props: Props<T>): JSX.Element => {
  const GenericComponentHackInstance = GenericComponentHack<T>()
  // @ts-ignore
  return <GenericComponentHackInstance {...props} />
}

这感觉很难看,有没有别的办法?

gmol1639

gmol16391#

是的,defineComponent从3.3版本开始有另一个带函数的签名。你可以在这里阅读更多关于这方面的内容
doc中的例子:

const Comp = defineComponent(
  <T extends string | number>(props: { msg: T; list: T[] }) => {
    // use Composition API here like in <script setup>
    const count = ref(0)

    return () => {
      // render function or JSX
      return <div>{count.value}</div>
    }
  },
  // manual runtime props declaration is currently still needed.
  {
    props: ['msg', 'list']
  }
)

相关问题