defineProps withDefaults "The type is lacking the following properties from the specified type"

I am currently working on a custom Button component with some unique functionality:

<script lang="ts" setup>
import { computed, ref } from 'vue';

const {
  type = 'button',
  color = 'primary',
  disabled = false
} = defineProps<{
  href?: string;
  type: 'button' | 'submit' | 'reset' | undefined;
  color: string;
  disabled: boolean;
}>();

const element = ref<HTMLElement | null>(null);

defineExpose({
  focus: () => {
    element.value?.focus();
  },
});

const style =
  'inline-flex justify-center rounded-sm shadow-sm px-3 py-2 text-sm font-semibold focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus:outline focus:outline-2 focus:outline-offset-2';

const colors = new Map([
  [
    'primary',
    'bg-lime-600 text-white hover:bg-lime-700 focus-visible:outline-lime-700 focus:outline-lime-700',
  ],
  [
    'base',
    'bg-neutral-600 text-white hover:bg-neutral-700 focus-visible:outline-neutral-700  focus:outline-neutral-700',
  ],
  [
    'red',
    'bg-red-600 text-white hover:bg-red-700 focus-visible:outline-red-700 focus:outline-red-700',
  ],
  [
    'white',
    'bg-white text-neutral-900 ring-1 ring-inset ring-neutral-300 hover:bg-neutral-50 focus-visible:outline-neutral-400 focus:outline-neutral-400',
  ],
]);

const disabledStyles = computed(() =>
  disabled ? ' opacity-50 cursor-not-allowed' : null
);

const styles = computed(
  () => `${style} ${colors.get(color)}${disabledStyles.value}`
);
</script>
<template>
  <component :is="href ? 'a' : 'button'" ref="element" :class="styles" v-bind="href ? { href } : { type }">
    <slot />
  </component>
</template>

Currently, I'm integrating this custom button within another component and here is how it's being used:

<script lang="ts" setup>
import Button from '@/components/Button.vue';
import { onMounted, ref } from 'vue';

const emit = defineEmits(['cancel', 'proceed']);

const buttonRef = ref<HTMLElement | null>(null);

onMounted(() => {
  if (buttonRef.value) {
    buttonRef.value.focus();
  }
});
</script>

<template>
  <div>
    // ...
    <div class="mt-6 grid grid-flow-row-dense grid-cols-2 gap-3">
      <Button ref="buttonRef" @click="emit('cancel')">Abort</Button>
      <Button color="red" @click="emit('proceed')">
        <slot name="button" />
      </Button>
    </div>
  </div>
</template>

However, upon compiling the code for production using Vite, an error message pops up:

Argument of type '{ ref: string; onClick: any; }' is not assignable to parameter of type '{ readonly href?: string | undefined; readonly type: "button" | "submit" | "reset" | undefined; readonly color: string; readonly disabled: boolean; } & VNodeProps & ... 4 more ... & Record<...>'.

Type '{ ref: string; onClick: any; }' is missing the following properties from type '{ readonly href?: string | undefined; readonly type: "button" | "submit" | "reset" | undefined; readonly color: string; readonly disabled: boolean; }': type, color, disabled

<Button ref="buttonRef" @click="emit('cancel')">Abort

If anyone has encountered this issue before and knows how to resolve it, kindly provide some guidance. Thank you!

Answer №1

When you declare

defineProps<{
  href?: string;
  type: 'button' | 'submit' | 'reset' | undefined;
  color: string;
  disabled: boolean;
}>()

You are setting three required props (type, color, disabled). But in the Button component, these props are not set:

 <Button ref="buttonRef" @click="emit('cancel')">Abort</Button>

There are a few ways to address this issue:

  1. Make the props non-required by adding '?' after their names, as done for href.

  2. Provide values for the required props (set type, color, and disabled).

  3. Adjust compiler options to ignore inconsistencies, but Vue will still warn about missing required props (not recommended).

In your situation:

color: Assign a value or make it non-required with a default (e.g., primary)

disabled: Assign a value or make it non-required with a default (e.g., false)

type: Consider using isLink and buttonElementAttrs instead of type and href.

Redefine your Button Component with these new props:

<template>
    <component :is="isLink ? 'a' : 'button'" ref="element" :class="styles" v-bind="buttonElementAttrs">
        <slot />
    </component>
</template>

Then use the following code to display your button:

 <Button ref="buttonRef" @click="emit('cancel')" :isLink="false" :buttonElementAttrs="{ href: 'my/fancy/url' }">Abort</Button>

Answer №2

Default destructuring is not the same as using withDefaults().
Here is a simple example:

interface Options {
  name?: string;
  category: 'A' | 'B' | undefined;
  value: number;
}

withDefaults(defineValues<Options>(), {
  category : () => 'A',
  value : () => 100,
});

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

Refine the Crossfilter dimension according to the specified date range

What is the proper way to filter a date range using Crossfilter? The code above does not seem to yield any results, but I am certain that there are records within that specified time period. Var myDimension = CrossFilterObj.dimension(function(d) { retur ...

Another drop-down is hiding the bootstrap-select drop-down from view

What could be causing some parts of the first drop-down menu to be hidden by another drop-down menu below in the code snippet provided? <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv= ...

Implementing a JQuery click method within a class structure

I'm having trouble getting the functionality of the .click function to work on my page unless I paste it into the browser console. In my class, this is what I have: var myClass = function(){ var toggleChecked = function(){ $('#myCheck ...

Issue with Tailwind causing content to extend beyond screen with horizontal scrolling

I have a React-based NextJS application using Tailwind CSS. There is a page component that displays a list of individuals sorted from A to Ö (Swedish alphabet). In the mobile view, the user experience requires the list of alphabetical letters to be visibl ...

Using Javascript outside of the AngularJS environment

I am trying to utilize Javascript functions outside the controller in Angular JS instead of using a service within a module. Is this allowed? For instance: var UrlPath="http://www.w3schools.com//angular//customers.php" //this section will store all the f ...

Optimizing event mapping with the jQuery "on" function

CODE I: $searchBoxParent.on({ mouseover: function() { $this = $(this); $this.parent().find(".hlight").removeClass('hlight'); $this.addClass("hlight"); }, mouseout: function() { $this = $(this); ...

I'm interested in exploring different database implementation patterns in JavaScript. What kinds of approaches can I consider?

As someone who is relatively new to exploring JavaScript, I have been immersed in experimenting with a node test app and MongoDB. I am eager to delve into the database aspect of the app but finding myself uncertain about the most commonly used patterns in ...

Fetching JSON data cross-domain with the help of JavaScript or JQuery

I am currently attempting to retrieve JSON data from this specific url. However, I am encountering difficulties in making it function as intended. The goal is to seamlessly integrate the school's lunch menu utilizing NutriSlice. We are leveraging Ris ...

What's the best way to link two http requests in AngularJS?

Currently, I am facing the challenge of chaining two http calls together. The first call retrieves a set of records, and then I need to fetch finance data for each individual record. flightRecordService.query().$promise.then(function (flightRecords) { $ ...

What is the method for including a placeholder (instead of a label) in the MUI 5 DatePicker component?

I'm looking to customize the placeholder text in MUI 5's date picker. You can find the MUI 5 datepickerlink here: https://mui.com/x/react-date-pickers/date-picker/ The desired outcome:: I've tried referring to this chat, but it hasn't ...

Guidelines for simultaneously modifying two dropdown select options

Is it possible to have one dropdown automatically change its value based on the selection made in another dropdown? For instance, if 'Value 1' is chosen from 'dropdown 1', can we set 'dropdown 2' to automatically display the ...

Concealing certain options in a dropdown list with jQuery Chosen

My app has a unique feature where it displays different dropdown lists based on previous selections. Specifically, I have two lists - one for vehicle Makes and the other for Models. When a specific Make is chosen, like BMW or Audi, the next list will only ...

Retrieve information from the parent element

I am working with two components: header.vue nav.vue In the header component, I have a button that, when clicked, should change a class in the nav component. However, I am struggling to access the parent component. How can I achieve this? In my index.pu ...

What is the method for passing an element object instead of an id in JSXGraph?

I'm attempting to modify var brd2 = JXG.JSXGraph.initBoard('box', {boundingbox: [-8.75, 2.5, 8.75, -2.5]}); to read as var brd2 = JXG.JSXGraph.initBoard(this.$('#box'), {boundingbox: [-8.75, 2.5, 8.75, -2.5]}); Due to the creat ...

The renderValue property is malfunctioning in the Material-UI native Select component

Whenever I utilize the native prop in the MUI Select component, the renderValue prop fails to function properly. Additionally, if I attempt to assign a custom value to the value prop, it does not display. Take a look at the code snippet below: const [selec ...

Eliminate the ending slash from your Nuxt application

Hello, I am currently working on a Nuxt Application and encountering an issue. After running the npm run build command and starting it with npm start, there seems to be an inconsistency with trailing slashes. During the build, the URL appears without a t ...

What is the best way to reload scripts each time a component is mounted?

My jQuery scripts include animation effects that need to be refreshed whenever something new is rendered on the page. However, I am facing an issue where the jQuery scripts are not being refreshed as needed. Below is my router configuration: export defau ...

Mongodb error occurred due to a duplicate key in the collection with the key value set

I need to set up multiple user accounts. The first account creation is successful, but I encounter an error when trying to create a new account: BulkWriteError: insertDocument :: caused by :: 11000 E11000 duplicate key error index: db.users.$friends. ...

"Vue is failing to actively update an input that relies on changes from another

I am working on a project where the selected country automatically determines the phone country code. I have set it up so that when I change the country, the corresponding country code should update as well. https://i.sstatic.net/861tq.png Within a custo ...

Stop all file uploads using jQuery

I have integrated the jQuery File Upload plugin () into my website for image uploads. Here is my code snippet: $('#fileupload').fileupload({ url: 'server/index.php', dataType: 'json', dropZone: $('#dropzone&a ...