Skip to content

RouteParams Type Alias | Vue Router

RouteParams is a type alias that defines the structure for route parameters extracted from URL paths. It provides type-safe access to dynamic route segments. 🔢

📋 Type Definition

typescript
type RouteParams = Record<string, RouteParamValue>

🎯 Purpose and Usage

The RouteParams type alias represents the parameters extracted from route paths. It's used throughout Vue Router for type-safe parameter handling in routes, navigation, and component props.

Key Characteristics:

  • Type Safety - Ensures proper parameter handling
  • String Values - All parameters are converted to strings
  • Flexible Structure - Supports optional and required parameters
  • Route Matching - Used in route resolution and matching

🔍 Type Structure

Basic Parameter Structure

typescript
// For route path: "/user/:id"
const params: RouteParams = {
  id: "123" // Always string values
}

// For route path: "/blog/:year/:month/:slug"  
const params: RouteParams = {
  year: "2023",
  month: "12",
  slug: "vue-router-guide"
}

Parameter Value Types

All parameter values are strings, but the type alias supports the underlying RouteParamValue type which can be:

typescript
type RouteParamValue = string | number | null | undefined
// But in practice, they're always converted to strings

💡 Practical Usage Examples

Accessing Route Parameters

vue
<script setup>
import { useRoute } from 'vue-router'
import { computed } from 'vue'

const route = useRoute()

// Basic parameter access
const userId = computed(() => route.params.id as string)
const postSlug = computed(() => route.params.slug as string)

// Multiple parameters
const blogParams = computed(() => ({
  year: route.params.year as string,
  month: route.params.month as string,
  slug: route.params.slug as string
}))

// Parameter validation with fallbacks
const safeUserId = computed(() => {
  const id = route.params.id
  return id ? String(id) : 'unknown'
})
</script>

Parameter-Based Logic

vue
<script setup>
import { useRoute } from 'vue-router'
import { computed, watch } from 'vue'

const route = useRoute()

// Watch for parameter changes
watch(() => route.params.id, (newId, oldId) => {
  if (newId && newId !== oldId) {
    loadUserData(newId as string)
  }
})

// Conditional rendering based on parameters
const showEditButton = computed(() => {
  return route.params.action === 'edit'
})

// Parameter validation
const isValidUser = computed(() => {
  const id = route.params.id as string
  return /^\d+$/.test(id) // Check if ID is numeric
})
</script>
typescript
import type { RouteParams } from 'vue-router'

class NavigationService {
  // Navigate to user profile
  static navigateToUserProfile(userId: string): void {
    const params: RouteParams = { id: userId }
    router.push({
      name: 'user-profile',
      params
    })
  }
  
  // Navigate to blog post
  static navigateToBlogPost(
    year: string, 
    month: string, 
    slug: string
  ): void {
    const params: RouteParams = { year, month, slug }
    router.push({
      name: 'blog-post',
      params
    })
  }
  
  // Create parameterized URL
  static createParameterizedPath(
    pathTemplate: string, 
    params: RouteParams
  ): string {
    let result = pathTemplate
    for (const [key, value] of Object.entries(params)) {
      result = result.replace(`:${key}`, value as string)
    }
    return result
  }
}

🔧 Advanced Patterns

Parameter Validation and Transformation

typescript
class ParameterProcessor {
  // Validate and transform route parameters
  static processUserParams(params: RouteParams): ProcessedUserParams {
    const validation = this.validateUserParams(params)
    if (!validation.isValid) {
      throw new Error(`Invalid parameters: ${validation.errors.join(', ')}`)
    }
    
    return {
      userId: parseInt(params.id as string),
      action: params.action as string || 'view',
      tab: params.tab as string || 'profile'
    }
  }
  
  private static validateUserParams(params: RouteParams): ValidationResult {
    const errors: string[] = []
    
    // Validate required parameters
    if (!params.id) {
      errors.push('User ID is required')
    } else if (!/^\d+$/.test(params.id as string)) {
      errors.push('User ID must be numeric')
    }
    
    // Validate optional parameters
    if (params.action && !['view', 'edit', 'delete'].includes(params.action as string)) {
      errors.push('Invalid action parameter')
    }
    
    return { isValid: errors.length === 0, errors }
  }
  
  // Extract parameters from current route
  static extractCurrentParams(): RouteParams {
    return { ...router.currentRoute.value.params }
  }
  
  // Merge parameters with existing ones
  static mergeParams(baseParams: RouteParams, additionalParams: RouteParams): RouteParams {
    return { ...baseParams, ...additionalParams }
  }
}

Type-Safe Parameter Handling

typescript
// Define application-specific parameter types
interface UserRouteParams extends RouteParams {
  id: string
  action?: 'view' | 'edit' | 'delete'
  tab?: string
}

interface BlogRouteParams extends RouteParams {
  year: string
  month: string
  slug: string
}

// Type-safe parameter access
function getUserParams(params: RouteParams): UserRouteParams {
  return {
    id: params.id as string,
    action: params.action as 'view' | 'edit' | 'delete',
    tab: params.tab as string
  }
}

function getBlogParams(params: RouteParams): BlogRouteParams {
  return {
    year: params.year as string,
    month: params.month as string,
    slug: params.slug as string
  }
}

Parameter-Based Routing Utilities

typescript
class ParameterRouting {
  // Check if current route matches parameter pattern
  static isMatchingRoute(pattern: string, params: RouteParams): boolean {
    const currentRoute = router.currentRoute.value
    return Object.keys(params).every(key => 
      currentRoute.params[key] === params[key]
    )
  }
  
  // Get parameter differences between routes
  static getParameterChanges(
    oldParams: RouteParams, 
    newParams: RouteParams
  ): string[] {
    const changed: string[] = []
    
    const allKeys = new Set([
      ...Object.keys(oldParams),
      ...Object.keys(newParams)
    ])
    
    for (const key of allKeys) {
      if (oldParams[key] !== newParams[key]) {
        changed.push(key)
      }
    }
    
    return changed
  }
  
  // Create parameterized navigation
  static createParameterizedNavigation(
    baseLocation: RouteLocationRaw,
    params: RouteParams
  ): RouteLocationRaw {
    if (typeof baseLocation === 'string') {
      // Handle string paths
      let path = baseLocation
      for (const [key, value] of Object.entries(params)) {
        path = path.replace(`:${key}`, value as string)
      }
      return path
    } else if (baseLocation.path) {
      // Handle path objects
      let path = baseLocation.path
      for (const [key, value] of Object.entries(params)) {
        path = path.replace(`:${key}`, value as string)
      }
      return { ...baseLocation, path }
    } else {
      // Handle named routes
      return {
        ...baseLocation,
        params: { ...baseLocation.params, ...params }
      }
    }
  }
}

🚨 Important Considerations

Parameter Type Conversion

typescript
// Route parameters are always strings when accessed
const params = route.params

// ✅ Correct: Treat as strings
const userId = params.id as string
const pageNumber = parseInt(params.page as string)

// ❌ Incorrect: Assuming specific types
const userId = params.id as number // Wrong! params.id is string

// ✅ Better: Explicit conversion
const numericId = parseInt(params.id as string)
const booleanFlag = params.flag === 'true'

Optional vs Required Parameters

typescript
// Route definition with different parameter types
const routes = [
  {
    path: '/user/:id',          // Required parameter
    component: UserProfile
  },
  {
    path: '/blog/:year?/:month?', // Optional parameters
    component: BlogArchive
  },
  {
    path: '/search/:query*',     // Repeatable parameter
    component: SearchResults
  }
]

// Parameter access patterns
const userParams = route.params // { id: string }
const blogParams = route.params // { year?: string, month?: string }
const searchParams = route.params // { query?: string[] }

📚 Best Practices

Parameter Validation Patterns

typescript
class ParameterValidator {
  // Validate parameters with schema
  static validateWithSchema(
    params: RouteParams, 
    schema: ParameterSchema
  ): ValidationResult {
    const errors: string[] = []
    
    for (const [key, rule] of Object.entries(schema)) {
      const value = params[key]
      
      if (rule.required && !value) {
        errors.push(`Parameter ${key} is required`)
        continue
      }
      
      if (value && rule.pattern && !rule.pattern.test(value as string)) {
        errors.push(`Parameter ${key} has invalid format`)
      }
      
      if (value && rule.allowedValues && 
          !rule.allowedValues.includes(value as string)) {
        errors.push(`Parameter ${key} has invalid value`)
      }
    }
    
    return { isValid: errors.length === 0, errors }
  }
  
  // Common validation rules
  static commonRules = {
    id: { pattern: /^\d+$/, required: true },
    slug: { pattern: /^[a-z0-9-]+$/ },
    page: { pattern: /^\d+$/, allowedValues: null }
  }
}

Parameter Utilities

typescript
class ParameterUtils {
  // Safe parameter access with defaults
  static getParam(params: RouteParams, key: string, defaultValue: string = ''): string {
    const value = params[key]
    return value ? String(value) : defaultValue
  }
  
  // Get numeric parameter with validation
  static getNumericParam(params: RouteParams, key: string, defaultValue: number = 0): number {
    const value = params[key]
    if (!value) return defaultValue
    
    const numeric = parseInt(value as string, 10)
    return isNaN(numeric) ? defaultValue : numeric
  }
  
  // Get boolean parameter
  static getBooleanParam(params: RouteParams, key: string, defaultValue: boolean = false): boolean {
    const value = params[key]
    if (!value) return defaultValue
    
    return value === 'true' || value === '1'
  }
  
  // Get array parameter
  static getArrayParam(params: RouteParams, key: string): string[] {
    const value = params[key]
    if (!value) return []
    
    return Array.isArray(value) ? value : [value as string]
  }
}

💡 Pro Tip: Always validate and sanitize route parameters before using them in your application. Use type guards and validation functions to ensure parameter safety and prevent runtime errors.

🚀 Vue Router - 让前端路由变得简单而强大 | 构建现代化单页应用的最佳选择