如何在 Vue 3 TypeScript 中处理联合类型 Props 并避免数组转换错误?

新手上路,请多包涵

TypeScript vue3 中 CustomComponent组件的props是一个联合类型, 把联合类型弄成数组后使用,报错了,请问为什么会这样? 2aa7a6f052ebe58ff4d4142779233273.pngb51782bc1d5a7d8b4b9c7eb2b0c53a05.png54543e89519ba2b04e6a72fbb00660c7.png

希望能正常使用 ts不会报错

阅读 637
avatarAI BotBETA

在 Vue 3 中使用 TypeScript 处理联合类型 Props 并避免数组转换错误时,通常需要注意几个关键点。首先,联合类型直接转换为数组在 TypeScript 中是不被直接支持的,因为 TypeScript 需要明确的类型信息来确保类型安全。

问题分析

从你的问题描述和图片来看,你试图将一个联合类型的 Prop 转换为一个数组,但遇到了类型错误。这通常是因为 TypeScript 无法自动推断或理解这种转换是安全的。例如,如果你有一个 Prop 是 string | number 类型,直接将其视为数组 string[] | number[] 类型是不合适的,因为单个值并不等同于数组。

解决方案

  1. 避免不必要的数组转换
    如果 Prop 本身是联合类型(如 string | number),并且你不需要将其作为数组处理,那么直接使用它即可。
  2. 条件渲染或计算属性
    如果你需要根据 Prop 的类型进行不同的处理(包括转换为数组),你可以使用条件渲染或计算属性来分别处理每种类型。

    <script lang="ts">
    import { defineComponent, computed } from 'vue';
    
    export default defineComponent({
      props: {
        myProp: {
          type: [String, Number] as () => string | number,
          required: true
        }
      },
      setup(props) {
        const myPropAsArray = computed(() => {
          if (typeof props.myProp === 'string') {
            return [props.myProp];
          }
          if (typeof props.myProp === 'number') {
            return [props.myProp];
          }
          // 理论上这里不应该到达,因为类型已经定义
          return [];
        });
    
        return {
          myPropAsArray
        };
      }
    });
    </script>
  3. 使用泛型或类型断言
    如果确实需要将 Prop 转换为数组,并且确信这样做是安全的,可以使用类型断言来告诉 TypeScript 你知道自己在做什么。

    const myPropArray = [props.myProp] as (string | number)[];

但请注意,这种方法降低了类型安全,因为你在告诉 TypeScript “相信我,我知道这个值可以安全地作为一个数组元素”。

  1. 重新考虑 Props 的设计
    如果经常需要将 Prop 转换为数组,可能需要重新考虑 Props 的设计。例如,如果总是期望一个数组,那么 Prop 的类型应该直接定义为数组类型。

    props: {
      myProp: {
        type: Array as () => (string | number)[],
        required: true
      }
    }

结论

处理 Vue 3 TypeScript 中的联合类型 Props 时,重要的是要保持类型清晰和类型安全。避免不必要的类型转换,并使用条件渲染、计算属性或类型断言来根据需要进行处理。同时,重新考虑 Props 的设计,以确保它们满足你的组件需求。

1 个回答

我写了个demo,无法复现

父组件

<template>
  <HelloWorld :is="obj.is" :value="obj.value" />

  <div v-for="(item,index) in arr" :key="index">
    <HelloWorld :is="item.is" :value="item.value" />
  </div>
</template>

<script lang="ts" setup>
//
  const obj = {
    is: 'string',
    value: '123',
  }
  const arr = [
    {
      is: 'string',
      value: '123',
    },
  ]
</script>

子组件

<template>
  <div />
</template>

<script setup lang="ts">
//
  type Props = { id: 'string', value: string } | { id: 'number', value: number } | { id: 'boolean', value: boolean }

  const props = defineProps<Props>()

  console.log(props)
</script>
推荐问题
logo
Microsoft
子站问答
访问
宣传栏