10

As an exercise, I'm trying to define the FontAwesome Vue implementation in TypeScript. They allow the icon prop to have different types:

icon: {
    type: [Object, Array, String],
    required: true
},

I tried to add a validation to it, but then props in setup seems broken:

validator: (prop) => {
    if (typeof prop === 'object') {
        const obj = prop as any;
        return (obj.prefix && obj.iconName);
    } else if (Array.isArray(prop) && prop.length === 2) {
        return true;
    }
    return typeof prop === 'string';
}
Property 'icon' does not exist on type 'Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; slice?: string[] | undefined; ... 16 more ...; flat?: unknown[] | undefined; }> | Readonly<...>'.
Property 'icon' does not exist on type 'Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; slice?: string[] | undefined; ... 16 more ...; flat?: unknown[] | undefined; }>'.Vetur(2339)

Without the validator, I can do this in the setup:

setup(props) {
    let icon: Icon; // simple interface I defined having prefix and iconName
    if (typeof props.icon === 'object') {
        icon = props.icon as Icon;
    } else if (Array.isArray(props.icon) && props.icon.length === 2) {
        icon = {
            prefix: props.icon[0],
            iconName: props.icon[1],
        };
    } else if (typeof props.icon === 'string') {
        icon = {
            prefix: 'l',
            iconName: props.icon as string,
        };
    }
}

Any ideas on how I could make the validation work with this setup? or is there a better way to define a prop with multiple types?

WoJ
  • 27,165
  • 48
  • 180
  • 345
Thomas
  • 6,325
  • 4
  • 30
  • 65
  • Does this answer your question? [How to add multiple data types for VueJs Props?](https://stackoverflow.com/questions/53608244/how-to-add-multiple-data-types-for-vuejs-props) – Frenchcooc May 11 '22 at 08:34

2 Answers2

29

From how I understand the docs something like the following would be needed:

import { defineComponent, PropType } from 'vue'

interface Icon {
  src: string
  width: number
  height: number
}

const Component = defineComponent({
  props: {
    icon: {
        type: [Object, Array, String] as PropType<Icon | Icon[] | string>,
        required: true
    },
  }
})
Anbraten
  • 701
  • 7
  • 9
0

You can cast it to the type.

{
    name: 'Bob' as string | number,
}
kinoli
  • 109
  • 2
  • 5