The defineProps<SomePropType>() method is not rendering the props as expected

I have various components, with a parent element where I attempted to pass props using the syntax defineProps<{}>(). The setup is simple, I have a types.ts file at the root level, a parent Vue file (referred to as CardItem), and multiple components.

Here's what I've done so far...

/* types.ts */
export type IItem = { title: string; description: string };

/* DetailedCard.vue */
<script setup lang="ts">
import TestItem from "../test.vue";
</script>

<TestItem :title="'hello world'" :description="'lorem ipsum dolor sit amet'" />

/* TestItem.vue */
<script setup lang="ts">
import type { IItem } from "@/types";
const { title, description } = defineProps<IItem>();
</script>

<template>{{ title }} {{ description }}</template>

The error(s) I'm encountering:

[@vue/compiler-sfc] type argument passed to defineProps() must be a literal type, or a reference to an interface or literal type.

Additionally, when I try to use it this way...

... ...

interface Item extends IItem {}
const { title, description } = defineProps<Item>();

I receive warnings at runtime:

runtime-core.esm-bundler.js:40 [Vue warn]: Property "title" was accessed during render but is not defined on instance. at

<Test title="hello" description="world" >

runtime-core.esm-bundler.js:40 [Vue warn]: Property "description" was accessed during render but is not defined on instance. at
<Test title="hello" description="world" >

The only solution that works is if I directly declare an interface/type in the TestItem component itself.

interface Item { title: string; description: string; };
const { title, description } = defineProps<Item>();

So, what could possibly be going wrong here!
Thank you!

Answer №1

This specific behavior is to be expected. When referencing the "TypeScript with Composition API" page within the documentation, we come across this particular section, which clearly outlines the necessary steps:

To ensure that the correct runtime code is generated, the generic argument for defineProps() must fall into one of these categories:

  • An object literal type:
defineProps<{ /*... */ }>()
  • A reference to an interface or object literal type in the same file:
interface Props {/* ... */}

defineProps<Props>()

Furthermore, it explicitly states that importing the type from another file is not allowed:

While the interface or object literal type may make use of types imported from external files, the generic argument passed to defineProps itself must not be a type imported from elsewhere.

Hence, the only viable options for defining your props are as follows:

interface Item { title: string; description: string; };

const { title, description } = defineProps<Item>();

or by embedding the interface directly:

const { title, description } = defineProps<{ title: string; description: string; }>();

Answer №2

The information provided in the accepted answer may no longer be entirely accurate for Vue 3.3 and above. According to the official documentation:

As of version 3.3, Vue has addressed some of the limitations mentioned. The latest release now allows for referencing imported types and a subset of complex types within type parameters. However, certain complex types that rely on actual type analysis, such as conditional types, are still not fully supported due to the AST-based type to runtime conversion process. While you can use conditional types for individual props, it's not possible for the entire props object.

It's important to note the restriction regarding complex types, which may necessitate defining types directly in the Single File Component (SFC) file, especially when working with generic components like the example below:

// Example.vue
<script setup lang="ts" generic="T">
import type SomeComplexTypeWithGeneric from "somewhere";

defineProps<SomeTypeWithGeneric<T>>() // Potential runtime errors

</script>

// somewhere.ts
...
type SomeComplexTypeWithGeneric<T> = Pick<SomeOtherType<T>, "someProp"> & {
    anotherProp: any
}
...

If SomeComplexTypeWithGeneric is defined inside Example.vue, everything should function correctly.

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

Swap out a collection of objects for a different collection of objects

I need to replace the content of array1 with the content of another array2 while keeping the same references and indexes in array1: let array1 = [ { book : { id : 2, authorId : 3} } , { book : { id : 3, authorId : 3} }, { book : { id : 4, authorId : ...

Testing Vue components with Typescript and Jest does not display the expected values in the HTML output

Recently, I decided to focus on Test-Driven Development (TDD) using Typescript, so I started a new Vue project with vue-cli. I specifically chose Vue3, Typescript, and Jest for this project. However, when I ran the unit test initially, it failed to execute ...

Navigating the parent scope in Angular using TypeScript

Is there a way to access the parent Controller's scope from within the TypeScript class? Here is the code snippet: export class EntityOverviewCtrl extends AbstractCtrl { public static $inject = ["$state", "$http", "CurrentSession"]; publi ...

Issues with concealing the side menu bar in Vue.js

I've been attempting to conceal the side menu bar, with the exception of the hamburger icon when in the "expanded" state. Despite my efforts to modify the CSS code, I am still struggling to hide the small side menu bar. The following images represent ...

Angular 10 introduces a new approach to handling concurrency called "forkJoin"

Here is the code I have: async getBranchDetails() ----component method { let banks = this.bankDataService.getBanks(); let branchTypes = this.branchDataService.getBranchTypes(); forkJoin([banks,branchTypes]).subscribe(results => { ...

Is your Angular2 form page experiencing reloading issues?

I am currently incorporating Angular2 into my project. I am facing an issue where the page keeps refreshing, and I'm unable to determine the cause. Below is a snippet of my form: <form> <div class="form-group"> ...

"Exploiting the Power of Nullish Coalescing in Functional

The interface I am working with is defined below: interface Foo { error?: string; getError?: (param: any) => string } In this scenario, we always need to call the function getError, but it may be undefined. When dealing with base types, we can us ...

Utilize Typescript to generate an object that contains a partial interface

Seeking assistance with an issue. We are working with two interfaces: interface IUserEntity { Id: number; FirstName: string; LastName: string; } interface IUserEntityMethods { GetFullName(): string; } I am trying to create an object tha ...

What is the best method for displaying a view on a new page in Angular 2?

Currently, I am facing a challenge with my Angular 2 project. I am struggling to figure out how to make a route open a new view instead of simply rendering in the same page. My goal is for the route to lead to a completely separate view rather than stayi ...

Angular - Implementing *ngIf based on URL parameters

Is it possible to display an element based on specific queryParams included in the URL? For example: ngOnInit() { this.route.queryParams.subscribe(params => { console.log(params); }); } If I want to achieve something similar to this: ...

Creating subclass mappings and defining subclasses dynamically using Typescript at runtime

I am puzzled by the structure of 3 classes: A, B, and C. Both B and C extend the abstract class A. abstract class A { public name: string; constructor(name: string) { this.name = name; } abstract getName(): string; } class B extends A { g ...

How can I redirect a page using an axios interceptor in Next.js?

Is there a way to redirect the page in an axios interceptor when dealing with server-side rendering limitations? Unfortunately, I am unable to access the server side context in the axios interceptor. I have tried using next/router but it only works on the ...

How to dynamically inject HTML content from a child component into a different component using Angular 5

Is it possible to customize the content of a reusable header section based on the current route data in Angular? The header currently displays a title and description pulled from the route data property. My concern is how to dynamically inject different H ...

Using assets in data property or methods in Vue 3 with Vite - how to efficiently manage and access resources

Recently delving into Vue 3 and vite, I've encountered a peculiar issue during production build. In development, everything runs smoothly but when I switch to production, the assets defined in the data property are inexplicably ignored, leading to a 4 ...

Steps for resetting the Vue 3 scaffolding

Two options to scaffold a new Vue project are npm init vue@latest and npm create vue@3. I recall there is a specific command that allows you to re-initialize the scaffolding process in order to add additional features like TypeScript or Cypress. Unfortuna ...

Using Angular's async, you can retrieve a value returned by a promise

Within the library I am currently utilizing, there is a method called getToken which can be seen in the following example: getApplicationToken() { window.FirebasePlugin.getToken(function(token) { console.log('Received FCM token: ' + to ...

Unable to reference the namespace 'ThemeDefinition' as a valid type within Vuetify

Looking to develop a unique theme for Vuetify v3.0.0-alpha.10 and I'm working with my vuetify.ts plugin file. import "@mdi/font/css/materialdesignicons.css"; import "vuetify/lib/styles/main.sass"; import { createVuetify, ThemeDefinition } from "v ...

Refreshing a page with a 404 error in Angular 2 while in production mode and without the useHash configuration

I've encountered an issue while using Angular 2 without the useHash feature. When trying to visit the URL directly in a browser, I'm getting a 404 not found error. I have searched extensively and attempted various solutions including: Adding L ...

Using react-hook-form to easily update form data

While working on my project with react-hook-form for updating and creating details, I encountered a problem specifically in the update form. The values were not updating properly as expected. The issue seems to be within the file countryupdate.tsx. import ...

Guide to importing a JSON file into Vue.js and HTML

I'm a beginner in Vue and not very familiar with HTML I'm attempting to import data from a JSON file into my interface to display it for the user. Below is the structure of the JSON: [ { "Title": "SOFT-STARTER", "Cod&q ...