Using Vue3 with TypeScript for props with multiple types

For a challenge, I am currently attempting to characterize the implementation of FontAwesome Vue in TypeScript. The icon prop in this implementation can have various types:

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

I tried to incorporate validation for it, but encountered an issue with props in setup:

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)

Even without the validator, I am able to do this in the setup:

setup(props) {
    let icon: Icon; // a simple interface I created with 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,
        };
    }
}

Do you have any suggestions on how I could implement the validation within this setup? Or perhaps there is a more efficient way to define a prop with multiple types?

Answer №1

Based on my interpretation of the documentation, it seems that a structure similar to the following would be necessary:

import { defineComponent, PropType } from 'vue'

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

const CustomComponent = defineComponent({
  props: {
    icon: {
        type: [Object, Array, String] as PropType<Icon | Icon[] | string>,
        required: true
    },
  }
})

Answer №2

To convert it to the appropriate data type, you can use casting.

{
    name: 'Bob' as string | number,
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can someone confirm if I am importing this png file correctly? I am encountering an error with Vite, here is my code

Error: TypeScript+ React + Vite [plugin:vite:import-analysis] Failed to find import "./assets/heropic.png" in "src\components\Hero.tsx". Are you sure the file exists? Hello fellow developers! I am new to working with react and typescript. Curren ...

How can a component be built into a library using vue-cli and then imported?

Using the vue-cli, I build my lib with the following command: "build": "vue-cli-service build --target lib --name myLib ./src/component.vue", After the build, how do I import my component from the dist folder? I've attempted the following: // und ...

Are the styles in app.scss going to waste with Laravel and Vue?

I'm currently working on a Laravel and Vue project using the Frontend Scaffolding outlined in the documentation found here: https://laravel.com/docs/7.x/frontend $ composer require laravel/ui $ php artisan ui vue Once executed, this command will load ...

Tips for retaining input field content within a BootstrapVue table

Below is a BootstrapVue table I'm working with; https://i.sstatic.net/xu5Et.png The code, courtesy of this response, is showcased below; new Vue({ el: '#app', data() { return { filter: '', items: [ { i ...

Ways to dynamically access input errors

Exploring My Implementation I have devised a function that takes an argument to access specific formik errors dynamically. This requires using bracket notation instead of dot notation as shown below: import {useFormikContext} from 'formik'; fun ...

A step-by-step guide on reversing options in the Ant Design Cascader component

By default, the Cascader component's options are nested from left to right. I am looking to have them go from right to left instead. However, I could not find anything in the component's API that allows for this customization. Is it even possibl ...

The resolve.alias feature in webpack is not working properly for third-party modules

Currently, I am facing an issue trying to integrate npm's ng2-prism with angular2-seed. The problem arises when importing angular2/http, which has recently been moved under @angular. Even though I expected webpack's configuration aliases to hand ...

Tips for referencing functions in TypeScript code

In regard to the function getCards, how can a type be declared for the input of memoize? The input is a reference to a function. import memoize from "fast-memoize"; function getCards<T>( filterBy: string, CardsList: T[] = CardsJSON.map((item, i ...

Can I inform the interpreter that my function in TypeScript specifically handles undefined and null values?

Consider a scenario where there is a method isEmpty that verifies if a value is empty, null, or undefined, and returns true accordingly. In TypeScript, this method may not effectively communicate to the interpreter, leading to a red underline in IDEs like ...

Syncing a line's position with the cursor in Angular using the ChartJs Annotation Plugin

I've been working on creating a crosshair using the annotation plugin, and while I've been able to modify the line's value, it doesn't seem to update on the chart. Here are the details of my chart options : public financialChartOptions ...

Utilizing svgr in NextJS with TypeScript and Webpack

I have a collection of separate svg files that I want to load in React and use as React components. Here is an example of how I am trying to do this: import SampleIcon from '@/components/editor/icons/add-column-after.svg'; <SampleIcon classNam ...

Typescript does not produce unused members

Having an issue with the JS code that TypeScript compiler is generating. Here's an example class: // Class export class UserDTO { Id: number; FirstName: string; LastName: string; DateOfBirth: Date; getFullName(): string { ...

The output from the map() function does not accurately represent the data returned by my REST call

Struggling with a REST call in my http.service.ts file while working with Angular version 7 and RxJS. The goal is to extract the "cod" value from a JSON response obtained from a REST call to the openweather API. However, when I add map() to extract the des ...

Discover how to access JSON data using a string key in Angular 2

Trying to loop through JSON data in angular2 can be straightforward when the data is structured like this: {fileName: "XYZ"} You can simply use let data of datas to iterate over it. But things get tricky when your JSON data keys are in string format, li ...

How can we limit the generic type T in TypeScript to ensure it is not undefined?

I have created a function called get(o, key), which is designed to work with any Object that meets the criteria of the { get: (key: K) => R } interface. Furthermore, I am interested in restricting the result variable R to not allow it to be undefined. ...

Error: To execute NPX command locally from Google Maps API documentation, make sure to call npm.load(callback) as required

Attempting to execute the Google Maps API example locally using this command: npx @googlemaps/js-samples init directions-waypoints googlemapssample However, every time I try to run the npx command locally, it fails after a short period and I encounter the ...

When utilizing a Vuetify table with a column filter, the table filter will not be implemented on the specified

I am currently utilizing Vuetify 2. I have implemented custom filters for both a table and one of its columns, as demonstrated in the following link: https://codepen.io/hobbeschild/pen/zYJMjVY?editors=101 An issue I'm facing is that when using the ...

Tips for sequentially arranging and rearranging an array of numbers, even when duplicates are present

Encountered a perplexing issue that has me scratching my head in an attempt to visualize a solution. Currently, I am working with an array of objects that appears as follows: let approvers = [{order:1, dueDate: someDate},{order:2, dueDate: someDate}, ...

What is the best way to integrate an array from an external JavaScript file into a Vue.js component?

I am struggling to import an array into a Vue component: This is my simplified component: <script type="text/babel"> const codes = require('./codes.js'); export default { props: [], data() { return { ...

The @Prop property decorator in Vue cannot be utilized as it is not compatible

I have a Vue 2 component with TypeScript: import Vue from 'vue'; import Component from 'vue-class-component'; import Prop from 'vue-property-decorator'; @Component({ template: require('./template.html'), }) expo ...