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

Vue3组件Props联合类型(TypeScript)使用问题求助

Vue3 联合类型Props的TypeScript类型窄化问题解决方法

这种实现完全可行,问题核心是defineProps返回的是响应式Proxy对象,TypeScript默认无法通过普通条件判断直接窄化其联合类型。以下是具体解决步骤:

1. 确保类型定义为可区分联合类型

先保证text-input.d.ts中的接口是可区分联合类型——所有变体接口共享唯一的区分字段(此处为type),每个变体的type值唯一且明确:

// text-input.d.ts
export interface BaseTextInputProps {
  modelValue: string | number
  placeholder?: string
}

export interface WithUnitTextInputProps extends BaseTextInputProps {
  type: 'withUnit'
  unit: string
  unitPosition?: 'left' | 'right'
}

export interface PasswordTextInputProps extends BaseTextInputProps {
  type: 'password'
  showToggle?: boolean
}

export interface SearchTextInputProps extends BaseTextInputProps {
  type: 'search'
  searchIcon?: boolean
}

export type TextInputProps = WithUnitTextInputProps | PasswordTextInputProps | SearchTextInputProps

2. 在组件中实现类型窄化

由于defineProps返回响应式Proxy,直接判断props.type无法让TypeScript正确识别类型,可通过以下两种方式处理:

方式一:通过unref获取原始对象后判断

使用Vue的unref工具获取props的原始普通对象,再进行类型判断:

<script setup lang="ts">
import { unref } from 'vue'
import type { TextInputProps } from './text-input.d.ts'

const props = defineProps<TextInputProps>()

const rawProps = unref(props)
if (rawProps.type === 'withUnit') {
  // TypeScript会正确识别rawProps为WithUnitTextInputProps,可安全访问unit
  console.log(rawProps.unit)
}
</script>

方式二:自定义类型守卫函数

编写类型守卫函数,明确告知TypeScript当前props的类型:

<script setup lang="ts">
import type { TextInputProps, WithUnitTextInputProps } from './text-input.d.ts'

const props = defineProps<TextInputProps>()

// 自定义类型守卫
function isWithUnitProps(props: TextInputProps): props is WithUnitTextInputProps {
  return props.type === 'withUnit'
}

if (isWithUnitProps(props)) {
  // TypeScript可正确识别props为WithUnitTextInputProps
  console.log(props.unit)
}
</script>

3. 模板中的类型处理

在模板中可直接调用自定义类型守卫函数渲染对应内容:

<template>
  <div class="text-input">
    <input v-model="modelValue" :placeholder="placeholder" />
    <!-- 调用类型守卫判断后,可安全访问unit属性 -->
    <span v-if="isWithUnitProps(props)" class="input-unit">{{ props.unit }}</span>
  </div>
</template>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 11:35:55