You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue+TypeScript中defineProps用never类型触发Vite报错求助

解决方案

问题根源

Vue单文件组件的编译器不支持将联合类型作为defineProps的泛型参数,这就是你看到报错的原因。React允许联合类型直接用于props,但Vue的SFC编译逻辑要求泛型参数必须是单一接口或字面量类型。

修复后的代码

<template>
  <component :is="component" :to="to" :href="href" @click="$emit('click')">
    <slot />
  </component>
</template>

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

// 定义包含所有基础属性的接口(含可选的to/href)
interface ButtonBaseProps {
  type?: string
  size?: "sm" | "md" | "lg"
  disabled?: boolean
  loading?: boolean
  to?: string
  href?: string
}

// 定义互斥类型:确保to/href不同时存在,或都不存在
type ButtonProps = 
  | (ButtonBaseProps & { to: string; href?: never })
  | (ButtonBaseProps & { href: string; to?: never })
  | (ButtonBaseProps & { to?: never; href?: never })

// 用对象式defineProps定义属性,添加运行时校验确保互斥,同时设置默认值
const props = withDefaults(defineProps<ButtonBaseProps>({
  to: {
    type: String,
    default: undefined,
    validator: (val?: string) => val === undefined || props.href === undefined
  },
  href: {
    type: String,
    default: undefined,
    validator: (val?: string) => val === undefined || props.to === undefined
  }
}), {
  type: "button",
  size: "md",
  disabled: false,
  loading: false
}) as ButtonProps

// 合并原computed逻辑到script setup
const component = computed(() => {
  if (props.to || props.href) return resolveComponent("NuxtLink")
  return "button"
})

// 定义emit类型
defineEmits<{
  click: []
}>()

// 定义组件名,替代原额外的script标签
defineOptions({
  name: "CButton"
})
</script>

关键说明

  1. 类型层面的互斥约束:
    先定义包含所有可选属性的ButtonBaseProps作为defineProps的泛型参数(满足Vue编译器要求),再通过类型断言将props转为ButtonProps联合类型,让TypeScript在编译时校验to和href的互斥性。

  2. 运行时校验:
    在to和href的validator函数中确保两者不同时存在,避免编译后用户传入非法值。

  3. 代码精简与Vetur支持:

    • 用defineOptions定义组件名,去掉冗余的第二个script标签;
    • 对象式defineProps能被Vetur正确识别,无需额外配置即可获得props提示。
  4. 兼容性:
    该方案适配Vue 3 + Nuxt 3 + TypeScript,符合script setup的最新规范,同时保留了你的核心需求:to和href二选一或都不传。

内容的提问来源于stack exchange,提问作者indiehjaerta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 12:40:13