How Vue3 enables components to share props

Having recently made the switch from Vue2 to Vue3, I find myself a bit perplexed about the best approach for sharing props among multiple components. My goal is to create input components that can share common props such as "type", "name", and so on. Previously, I achieved this using mixins, but I'm unsure if this method is still considered the most effective.

Allow me to illustrate an attempt I made utilizing the options-api:

// Home.vue
<template>
    <p>Home</p>
    <p>{{ type }}</p>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { sharedInputProps } from '../admin/composables/sharedInputProps'

export default defineComponent({
    props: {
        ...sharedInputProps,
    },
    setup() {
        return {
        }
    },
})
</script>
// sharedInputProps.ts
import { ComponentPropsOptions } from 'vue'

export const sharedInputProps: ComponentPropsOptions = {
    type: {
        type: String,
        required: true,
        default: 'text',
    }
}

This implementation works, but unfortunately, I do not receive any typehinting or autocompletion in my IDE regarding the props in Home.vue (in this particular case <p>{{ type }}</p>.

If we look at how I approached it with mixins:

// Home.vue
<template>
    <p>Home</p>
    <p>{{ type }}</p>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import InputProps from '../admin/mixins/InputProps.vue'


export default defineComponent({
    mixins:[
        InputProps,
    ],
    setup() {
        return {
        }
    },
})
</script>
// InputProps.vue
<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
    props: {
        type: {
            type: String,
            required: true,
            default: 'text',
        }
    },
})
</script>

This method functions as intended and provides accurate typehinting and autocompletion.

However, I am curious about how one would achieve this using the composition-api and the defineProps method. I managed to directly define the props in Home.vue with typehinting and autocompletion, demonstrated below:

// Home.vue
<template>
    <p>Home</p>
    <p>{{ type }}</p>
</template>

<script setup lang="ts">
import { defineProps, withDefaults } from 'vue'
interface Props {
    type?: string
}

const props = withDefaults(defineProps<Props>(), {
    type: 'text',
})

</script>

As stated in the documentation (https://vuejs.org/guide/typescript/composition-api.html#typing-component-props), loading from an external file is not supported.

Therefore, my question arises - given that using an external file with the composition-api is not yet supported and typehinting/autocompletion are absent when utilizing an external file with the options-api and the spread operator to destructure an object, is mixins still the preferred practice for prop sharing? Or could there be a misconfiguration in my sharedProps.ts file (or elsewhere)?

I am currently running Vue 3 version 3.2.47 and leveraging PHPStorm version 2023.1 as my IDE.

Answer №1

Utilizing the ComponentPropsOptions
type prevents sharedInputProps from being implicitly typed.

If sharedInputProps are meant to be compatible with the ComponentPropsOptions type, you can utilize the satisfies keyword in TypeScript 4.9 or later:

export const sharedInputProps = {
    type: {
        type: String,
        required: true,
        default: 'text',
    }
} satisfies ComponentPropsOptions

By using this method, the correct type is maintained when it's included as props: { ...sharedInputProps }, and allows for any errors to be easily identified where it was initially defined.

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

Retrieve an image file from Laravel API within Vue Cli 3

I have set up a Laravel API as my backend and Vue Cli 3 for the frontend of my project. I am currently facing an issue trying to access images from storage/app/avatars in Laravel from my Vue front end. To tackle this, I ran the php artisan storage:link com ...

Display a loading indicator with the shortest possible delay whenever utilizing the React Router v6 Link functionality

Integrate React and Router v6 App.tsx: const Page1 = lazy(() => pMinDelay(import('./views/Page1'), 500)) const Page2 = lazy(() => pMinDelay(import('./views/Page2'), 500)) return ( <Suspense fallback={<Loading/>}gt ...

How to access a static TypeScript variable in Node.js across different files

I encountered a situation like this while working on a node.js project: code-example.ts export class CodeExample { private static example: string = 'hello'; public static initialize() { CodeExample.example = 'modified'; } ...

Unexpected behavior with VueJS Select2 directive not triggering @change event

Recently, I implemented the Select2 directive for VueJS 1.0.15 by following the example provided on their official page. However, I am facing an issue where I am unable to capture the @change event. Here is the HTML code snippet: <select v-select="ite ...

The API endpoint returns a 404 not found error on NextJS 14 in the production environment, while it functions correctly on the local

I am in the process of creating a small website using NEXT JS 14. On my website, there is a contact us page that I have been working on. In the GetInTouch.tsx file, I have the following code: <Formik initialValues={{ ...

I noticed that when using Next.js with the `revalidate: 1` option on a static page, it is triggering two full F5 refresh actions instead of just one. I was hoping for

Currently, I have set up a blog post edit page in my Next.js project. The post pages are utilizing the Incremental Static Regeneration feature with a revalidation time of 1 second for testing purposes. In the future, I plan to increase this to a revalidat ...

Tips for modifying the properties of variables within an array using JavaScript

I have an array that holds variables used to control a specific template. divisionsListToManipulate: ['showActivitiesSection', 'hideAssignActionplanDiv', 'displayProp ...

Obtain an instance tuple from tuple classes using TypeScript 3.0 generic rest tuples type

When it comes to retrieving the correct instance type from a class type, the process typically involves using the following code: type Constructor<T = {}> = new (...args: any[]) => T class Foo {} function getInstanceFromClass<T>(Klass: Co ...

Animating transitions in a Vuetify data table

I am in the process of animating the data on a Vuetify data table. My objective is to make the current data slide out to the right when Next is clicked, and then have the new data slide in from the left. The current result I am getting can be viewed here: ...

After importing this variable into index.ts, how is it possible for it to possess a function named `listen`?

Running a Github repository that I stumbled upon. Regarding the line import server from './server' - how does this API recognize that the server object has a method called listen? When examining the server.ts file in the same directory, there is ...

Strange behavior detected in TypeScript generic function when using a class as the generic parameter

class Class { } const f0 = <T extends typeof Class> (c:T): T => { return c } const call0 = f0 (Class) //ok const f1 = <T extends typeof Class> (c:T): T => { const a = new c() return a //TS2322: Type 'Class' is not assigna ...

VueJS - Best Practices for Managing User IDs when Retrieving from API for User Deletion and Editing

Currently, I have a user listing feature in place. However, I am looking for a solution to delete a user when the admin clicks a button. How can you assist with this specific situation? <div v-if="users.length" class="users"> ...

Deploying a Nuxt3 application on a static hosting provider may result in an error related to the MIME type of an empty

I recently attempted to deploy my Nuxt3 application on a static file hosting service called "webempresa". After running the npm run generate command for static implementation, I encountered an error when trying to access the site. The console displayed the ...

Can we access local storage within the middleware of an SSR Nuxt application?

My Nuxt app includes this middleware function: middleware(context) { const token = context.route.query.token; if (!token) { const result = await context.$api.campaignNewShare.createNewShare(); context.redirect({'name': &a ...

Accessing Nested Arrays in Angular 8: Retrieving Data in HTML Template from Multiple Layers of Arrays

Hello there. I'm using an API that gives me the following data: (4) [{…}, {…}, {…}, {…}] 0: dueDate: "2018-03-26T00:00:00" priority: {priorityId: 1, priorityName: "Critical", priorityColor: "red"} statuses: Array(1) 0: ...

The Typescript intellisense feature in VS Code seems to be malfunctioning

While setting up typings for my Node server, the intellisense suddenly stopped working. I checked my tsconfig.json file: { "version": "0.1.0", "command": "tsc", "isShellCommand": true, "args": ["-p", "."], "showOutput": "silent", " ...

TS18047 jest error: "object may be null"

I'm currently working on a test (jtest) for an angular component, but it keeps failing due to this particular error. Any thoughts on how to resolve this? :) it("should require valid email", () => { spectator.component.email.setValue( ...

Tips for Customizing the Width of Your Material UI Alert Bar

At the moment, I have refrained from using any additional styling or .css files on my webpage. The width of the Alert element currently spans across the entire page. Despite my attempts to specify the width in the code snippet below, no noticeable change ...

Working with Vue 3 Composition API: manipulating an array of objects

I am working with an array stored in an external JSON file named "West.json" { "west" : [ { "id" : 1, "state": "CA" }, { "id" : 2, ...

Incorporate the operating hours of a Business

If I specifically choose Sunday and Monday with working hours ranging from 08.00 to 20.00, the output should be 1&08:00&20:00,2&08:00&20:00. How can I achieve this using Vue.js? This is my current code: <script> submitBox = new Vue( ...