Vue Props Definition with TypeScript
This challenge focuses on correctly defining props for a Vue component using TypeScript. Mastering props is crucial for building reusable and maintainable Vue applications, as they are the primary mechanism for passing data from a parent component to a child component.
Problem Description
Your task is to create a robust props definition for a Vue 3 component that accepts and validates various types of data. The component is designed to display user profile information, including their name, age, and an optional avatar URL.
Key Requirements:
- Define
propsusing TypeScript: Thepropsobject should be typed to leverage TypeScript's static typing capabilities. - Support primitive types: The
nameprop should be a required string, and theageprop should be a required number. - Support optional reference types: The
avatarUrlprop should be an optional string. If not provided, a default value should be used. - Implement custom validation: For the
ageprop, implement a custom validator to ensure the age is a non-negative number. - Use
definePropsmacro: Utilize the<script setup>syntax with thedefinePropsmacro.
Expected Behavior:
- The component should correctly receive and display the
nameandage. - If
avatarUrlis provided, it should be used; otherwise, a default placeholder image URL should be rendered. - If a negative number is passed for
age, the component should not render (or indicate an error, depending on implementation, but for this challenge, assume it simply won't render the relevant parts of the profile).
Examples
Example 1: Basic Usage
<script setup lang="ts">
import { defineProps } from 'vue';
const props = defineProps({
name: {
type: String,
required: true,
},
age: {
type: Number,
required: true,
validator: (value: number) => value >= 0,
},
avatarUrl: {
type: String,
required: false,
default: 'https://example.com/default-avatar.png',
},
});
</script>
<template>
<div>
<img :src="props.avatarUrl" alt="Avatar" width="50" height="50">
<h2>{{ props.name }}</h2>
<p>Age: {{ props.age }}</p>
</div>
</template>
Parent Component Usage:
<template>
<UserProfile
name="Alice Smith"
:age="30"
avatarUrl="https://example.com/alice.jpg"
/>
</template>
<script setup lang="ts">
import UserProfile from './UserProfile.vue';
</script>
Output (Rendered HTML Snippet):
<div>
<img src="https://example.com/alice.jpg" alt="Avatar" width="50" height="50">
<h2>Alice Smith</h2>
<p>Age: 30</p>
</div>
Explanation: All props are provided correctly, and the component renders with the provided data.
Example 2: Missing Optional Prop
<script setup lang="ts">
import { defineProps } from 'vue';
// ... (same props definition as Example 1) ...
</script>
<template>
<!-- ... (same template as Example 1) ... -->
</template>
Parent Component Usage:
<template>
<UserProfile
name="Bob Johnson"
:age="25"
/>
</template>
<script setup lang="ts">
import UserProfile from './UserProfile.vue';
</script>
Output (Rendered HTML Snippet):
<div>
<img src="https://example.com/default-avatar.png" alt="Avatar" width="50" height="50">
<h2>Bob Johnson</h2>
<p>Age: 25</p>
</div>
Explanation: The avatarUrl prop is not provided, so the default value is used.
Example 3: Invalid Prop Value (Custom Validator)
Parent Component Usage:
<template>
<UserProfile
name="Charlie Brown"
:age="-5"
avatarUrl="https://example.com/charlie.png"
/>
</template>
<script setup lang="ts">
import UserProfile from './UserProfile.vue';
</script>
Expected Behavior:
When this parent component is used, the UserProfile component will not render its content because the age prop fails the custom validator (age must be >= 0). In a real application, you might see a Vue warning in the console indicating the prop validation failure. For this challenge, consider that the component's template logic might conditionally render based on valid props. For simplicity, assume the template won't render if validation fails.
Constraints
- The
propsdefinition must be within a<script setup>block usinglang="ts". - The
definePropsmacro must be used. - All required props must be explicitly marked as
required: true. - The custom validator for
agemust returntrueif the value is valid, andfalseotherwise. - The
avatarUrlprop must have a default value.
Notes
- Consider the TypeScript types when defining your props. Vue 3's
definePropscan infer types from an array of strings or a single string, but for more complex scenarios like custom validators and default values, the object syntax is preferred and more explicit. - Think about how prop validation errors are handled in Vue. While you don't need to implement explicit error handling in the component's template for this challenge, understanding that validation failures occur is important.
- The
validatorfunction receives the value being passed to the prop.