What is the proper way to enhance properties?

In the process of developing a Vue3 app using Typescript, one of the components is designed to receive data through props. Initially, everything functioned smoothly with the basic setup:

   props: {
     when: String,
     data: Object
   },

However, I decided to enhance the props by incorporating default values, validators, and more:

  props: {
    when: {
      type: String,
      default: '',
      validator(value: string) {
        return ['today', 'tomorrow', 'later'].includes(value)
      },
      required: true
    },
    data: {
      type: Object,
      default() {
        return {}
      },
      required: true
    },
  },

Subsequently, TypeScript started flagging issues within the setup() function that are puzzling to me:


TS2345: Argument of type '"data"' is not assignable to parameter of type 'string & ((number | unique symbol | "length" | "toString" | "toLocaleString" | "concat" | "join" | "slice" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | ... 29 more ... | ((searchElement: never, fromIndex?: number | undefined) => boolean)) & string)'.

pertaining to the line:

let allEvents = toRef(props, 'data')

TS2339: Property 'when' does not exist on type 'Readonly<LooseRequired<Readonly<readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator<string> | undefined; length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; ... 17 more ...; includes?: ((searchElement: string, fromIndex?: number | undefined) =>...'.

related to the code:

  if (props.when === 'today') {
    // ...
  }

There are additional errors, but resolving them seems feasible once I identify the root cause.

Answer №1

There is a similarity in the issue at hand with another question where only the validator property was a regular function as discussed on Stack Overflow. In this case, both validator and default are regular functions (in different props), causing a breakdown in type inference for the props argument within setup(). I'm currently exploring the root problem through an open discussion on Stack Overflow.

An intriguing finding from your code snippet reveals a peculiar type representation for the props argument within setup(), resembling an intersection of keys of type string:

(parameter) props: Readonly<LooseRequired<Readonly<readonly unknown[] & {
    [x: number]: string;
} & {
    [Symbol.iterator]?: IterableIterator<string> | undefined;
    length?: number | undefined;
    toString?: string | undefined;
    toLocaleString?: string | undefined;
    ... 19 more ...;
    flat?: unknown[] | undefined;
}> | Readonly<...>>>

Solution

A workaround has been identified - replacing regular functions with arrow functions (where functions are required) in all props declarations:

export default defineComponent({
  props: {
    when: {
      type: String,
      default: '',

      //validator(value: string) {
      //  return ['today', 'tomorrow', 'later'].includes(value)
      //},
      validator: (value: string) => ['today', 'tomorrow', 'later'].includes(value), // ✅

      required: true
    },
    data: {
      type: Object,

      //default() {
      //  return {}
      //},
      default: () => ({}), // ✅

      required: true
    },
  },
})

This change results in a more structured type representation for the props argument:

(parameter) props: Readonly<LooseRequired<Readonly<{
    msg?: unknown;
    when?: unknown;
    data?: unknown;
} & {
    when: string;
    data: Record<string, any>;
} & {
    msg?: string | undefined;
}>>>

For demonstration purposes, check out the GitHub demo.

Answer №2

It is recommended that the validator be implemented as an arrow function:

when: {
  type: String,
  default: '',
  validator:(value:string)=>(['today', 'tomorrow', 'later'].includes(value)),
  required:true
 },
 

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

Vue: updating the :root CSS variable for a child component leads to an error - TypeError: Unable to access properties of undefined (reading 'style')

Fiddle: https://codesandbox.io/s/hardcore-mestorf-w1lsob?file=/src/App.vue In my project, I have created two simple files that are responsible for displaying a circle on the screen: https://i.stack.imgur.com/0ddI3.png The goal is to modify the circular ...

Unable to view the refreshed DOM within the specifications after it has been altered

For my current project, I am working on writing a functional spec that involves using Mocha/JSDOM and making assertions with 'chai'. The specific use case I am tackling is related to the function called updateContent: When this function is exec ...

The scale configuration for scale: x is not valid for creating a time scale chart using chart.js

I am currently utilizing VueJS and attempting to integrate a time scale chart using Chart.js. However, I encountered the following error: Invalid scale configuration for scale: x Below is my configuration : First, I have a component named Chart.vue with ...

Discovering the world of Promises in TypeScript and understanding how to return specific types

Transitioning from coding in Clojure for the past two years to TypeScript has been an interesting journey. However, I've hit a bit of a roadblock today. The issue lies with my interface: interface ICustomer { id: number, first_name: string } I ...

Issue with locating assets in Angular 6 build

Hey there! I'm currently facing an issue while trying to build my angular project. In the project, I am using scss with assets, and below is a snippet of how I have defined the background image: .ciao { background-image: url("../../assets/images/bc ...

Setting up ReactJS and TypeScript in a fresh MVC5 project from scratch

After extensively trying out various tutorials, I have yet to successfully run a basic MVC5 project using TypeScript and ReactJS. For reference, I have created these projects from scratch in Visual Studio 2015 with .NET 4.6.1, using the ASP.NET Web Applic ...

Mockery Madness - Exploring the art of mocking a function post-testing a route

Before mocking the process function within the GatewayImpl class to return the 'mockData' payload, I need to ensure that all routes are tested. import payload from './payloads/payloadRequire'; // payload for request import {Gate ...

Problem with z-index in VueJS: Child div z-index not functioning within v-dialog

I am facing an issue where I have brought a span to display a loading image inside the v-Dialog of a vuejs screen. The problem is that the v-dialog has a z-index of 220 set as inline style, causing my new span (loading image) to appear below the v-dialog. ...

Is there a way to obtain the component code prior to compiling in Vue2.x?

What is the purpose of this feature? <code-box title="基本" describe="button基本用法"> <i-button>Default</i-button> </code-box> I need to retrieve the default Slot String like <i-button>Default& ...

How can we avoid duplicating injectors in a child class when extending a class that already has injected services?

Delving deep into TypeScript inheritance, particularly in Angular 11, I've created a BasePageComponent to encompass all the necessary functions and services shared across pages. However, I've encountered an issue where my base class is becoming b ...

Looping through dynamic image sources using v-for

I have 10 images in the resources/images directory that I want to display using the vue3-carousel library. The image files are named 1.jfif, 2.jfif, and so on. However, when trying to bind the image source attribute with a variable, it results in an error: ...

The ReactDOM.createPortal modal has been successfully mounted onto the DOM, however, there seems to be no visible content

This project utilizes TypeScript and Next.js. Within it, there is a Modal component: interface ModalProps { onCancelModal: () => void; onAcceptModal: () => void; acceptEnabled: boolean; isLoading?: boolean; title: string; } const Modal: Re ...

Exploring the functionalities of class methods within an Angular export function

Is it possible to utilize a method from an exported function defined in a class file? export function MSALInstanceFactory(): IPublicClientApplication { return new PublicClientApplication({ auth: AzureService.getConfiguration(), <-------- Com ...

What's the best way to undo a CSS transition animation when deleting an active class?

I'm currenty working on a straightforward icon animation within a VueJS application. I've implemented a Vue transition to create a fade effect on the background elements, but I'm exploring options for a subtle upward shift animation specific ...

Next.js TypeScript project encountered an issue: "An error occured: 'TypeError: Cannot read property 'toLowerCase' of undefined'"

I am currently developing a Next.js TypeScript project and am facing a perplexing runtime error. The error message reads: TypeError: Cannot read property 'toLowerCase' of undefined This error is triggered in my code when I try to invoke the toLo ...

checkbox with an option tag

I need help with implementing multi-select checkboxes inside an Angular 4 application. The checkboxes are not appearing next to the team names as intended. Can anyone assist me with this issue? Below is a snippet of my HTML code: <select class="form-c ...

Creating packages for multiple Typescript projects that rely on a shared local module

I am currently developing a series of VSTS extensions, with each extension being its own independent Node project complete with its own package.json file and node_modules folder. The structure of the folders is as follows: - MyExtension - package.json ...

Execute the function only in response to changes in the data

I have a scenario where I am making an ajax call every 3 seconds to keep my app updated with rapidly changing information. However, the expensive function that I run inside the $.done() callback is causing my app to slow down. I want to optimize this proce ...

The Nuxt.js landing page is having trouble loading, but all other components are functioning perfectly

I successfully created a blog using Nuxtjs and everything was working perfectly in development mode. However, when I deployed the application to my cPanel server, the landing page (index.vue) at showed an error message saying This page could not be found ...

Triggering events in vue-router

I have two components called MyItem.vue and ChangeItem.vue. I'm attempting to emit an event in the ChangeItem.vue component and catch it in the MyItem.vue component, but for some reason, it's not working as expected. MyItem.vue <template> ...