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

Navigating a text input field in a NextJS application

Having trouble with handling input from a textarea component in a NextJS app. This is the structure of the component: <textarea placeholder={pcHld} value={fldNm} onChange={onChangeVar} className="bg-cyan-300" ...

Is it possible for React props to include bespoke classes?

In our code, we have a TypeScript class that handles a variety of parameters including type, default/min/max values, and descriptions. This class is utilized in multiple parts of our application. As we switch to using React for our GUI development, one of ...

Building an AngularJS Service with TypeScript that is Non-Singleton: A Step-by-Step Guide

I need help converting an AngularJS Typescript Service into a Non-Singleton. Can anyone provide guidance on how to achieve this? (Note: This is not the same as other questions that focus on achieving this in JS) I have included some simple pseudo code be ...

Currently honing my skills in Angular 2, but encountering an error stating "Bindings cannot contain assignments."

<app-employeecount [all]= "gettotalemployeescount()" <app-employeecount [all]= "gettotalemployeescount()" [male]= "gettotalmaleemployeescount()" [female]="gettotalfemaleemployeescount()" (on ...

Implementing a new field in a Node.js model using MongoDB

In my Node.js API, I have a user model working with MongoDB and Angular as the front-end framework. I decided to add a new field named "municipalityDateChange" to my user model. After doing so, I attempted to send an HTTP request from Angular to the Node A ...

Definition file for Typescript d.ts that includes optional properties in a function

Within my code, I have a function that offers different results based on specified options. These options dictate the type of return value. The function is currently written in plain JavaScript and I am looking to provide it with types using an index.d.ts ...

TypeScript functions with Generic Constraints return specific values rather than just types

function createGenericCoordinates<Type extends number | string>( x: Type, y: Type ) { return { x, y }; } const genericCoordinates = createGenericCoordinates(1, 2); // Error (TS2322) // Type 3 is not assignable to type 1 | 2 genericCoordinates ...

What is the proper way to add a string to a TypeScript array?

When attempting to add a string to a TypeScript array, I am encountering an error stating 'cannot push to undefined'. Is this the correct approach, or should I be using the spread operator instead? api.ts const api: IConfigName = {name: "getKey ...

The props are not being pushed as expected when using this.$router.push

I am currently in the process of navigating from one webpage to another and attempting to pass along properties to the new page component. Take a look at how I have set up my router.push below: this.$router.push({ name: 'settings', params: { ...

What is the best way to convert this tsc script into an npm script in package.json?

I am looking to execute the following script as an npm script: tsc src/*.tsc --outDir bin When I run this command directly in the terminal, it works as expected. However, when I add the exact same script to my package.json: { "scripts": { ...

Error in Angular 2 after transition to @types: encountering "require" name not found issue

After transitioning my project from old typings to types-publisher, I have successfully resolved most of my dependencies. However, I am consistently encountering an error that reads Cannot find name 'require'. Below is a snippet from my tsconfig. ...

Exploring the methods of connecting with data-checked and data-unchecked attributes in Angular

Utilizing a toggle switch, I am able to determine what text to display in the div by utilizing html attributes such as data-checked and data-unchecked. In addition, I have an Angular pipe that translates all texts on the website based on the selected lang ...

Encountering an Eslint issue: "Function missing return type" while adding a styled component to _document.tsx in Next.js

Setting up my NextJS project with styled components and Typescript has been my current focus. After consulting the official NextJS documentation, I successfully configured the _document.tsx file, which appears like this: import Document, { DocumentContext ...

Investigating SCSS Issues: The Problem with Absolute Imports

I am working on a project with the following structure: - my/project - assets - images - image-name.svg - source - components - MyComponent - MyComponent.module.scss - ... - ... ...

How should JSON files stored on the server side be properly utilized in Next.js?

Currently, I have a collection of JSON files that I expose through an API endpoint on my web application for global access. This allows different parts of the application to retrieve the data by sending a fetch request to itself... However, since this inf ...

What is the best way to define a precise return type for a JSX Element?

Is it possible to define a function that returns a Button element and what would the correct return type of the function be? For example: Ex: const clickMeButton = (): Button => { return ( <Button> Click Me </Button& ...

What is the best way to pre-fetch data using axios in Vue?

My app requires offline functionality for drivers operating in remote areas with limited internet access. To address this, I aim to pre-download all necessary data using Axios requests when an internet connection is available. This way, the app can retriev ...

The Angular Material Autocomplete component fails to show items upon upgrading the angular/material package to the newest version

Issue with Angular Material Autocomplete component not displaying items after updating angular/material package to the latest version. The autocomplete was functioning correctly with "@angular/material": "^2.0.0-beta.10" but encountered issues when update ...

flushMicrotasks does not function properly in conjunction with the image.onload event

Working on an Angular project, I'm currently developing an object with an image field. The method responsible for loading the image returns a promise that resolves in the onload function of the image. When trying to test this method using the flushMi ...

Clear the input field once an item has been successfully added to the array

I'm working on a CRUD application using an array. Once I add an item to the array, the HTML input field doesn't clear or reset. I've searched online but couldn't find a reset method in Angular. How can I clear the input field after addi ...