- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma binaryTargets for openssl 3.0 - nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal cron, http->https redirect - prisma: add origin_goods.delisted migration, sync missing schema (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz - api: CORS wildcard reflection, helmet CORP cross-origin, price backfill in persistProductDetail, categoryIcon ancestor fallback, mediaByColor per-color gallery in public goods detail - admin: /admin base path (vite + router) - import-data.mjs: udt_name casting, serial sequence advance fix
3.4 KiB
3.4 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Provide/Inject Has Limited Type Inference in Options API | MEDIUM | Injected properties in Options API are not automatically typed, requiring manual type assertions or type augmentation | gotcha |
|
Provide/Inject Has Limited Type Inference in Options API
Impact: MEDIUM - When using provide/inject with the Options API and TypeScript, injected properties won't be automatically typed. TypeScript will show errors that the property doesn't exist on the component, even though it works at runtime.
Task Checklist
- Be aware that Options API inject has limited type support
- Use type augmentation to add types to injected values
- Consider using typed computed wrappers for injected values
The Problem
// Provider component (parent)
import { defineComponent } from 'vue'
export default defineComponent({
provide() {
return {
theme: 'dark',
user: { id: 1, name: 'John' }
}
}
})
// Consumer component (child) - Options API
import { defineComponent } from 'vue'
export default defineComponent({
inject: ['theme', 'user'],
mounted() {
// TypeScript Error: Property 'theme' does not exist on type...
console.log(this.theme)
// TypeScript Error: Property 'user' does not exist on type...
console.log(this.user.name)
}
})
Solution 1: Type Augmentation
Augment the component type to include injected properties:
// types/injections.d.ts
import 'vue'
declare module 'vue' {
interface ComponentCustomProperties {
theme: 'light' | 'dark'
user: { id: number; name: string }
}
}
export {}
// Consumer component - now typed
import { defineComponent } from 'vue'
export default defineComponent({
inject: ['theme', 'user'],
mounted() {
// Now works - typed from ComponentCustomProperties
console.log(this.theme) // 'light' | 'dark'
console.log(this.user.name) // string
}
})
Note: This adds types globally to ALL components, not just those that inject these values.
Solution 2: Typed Computed Wrappers
Use the object syntax with computed property wrappers for type safety:
import { defineComponent } from 'vue'
interface User {
id: number
name: string
}
export default defineComponent({
inject: {
theme: {
from: 'theme',
default: 'light'
},
user: {
from: 'user',
default: () => ({ id: 0, name: 'Guest' })
}
},
computed: {
// Type via computed wrapper
typedTheme(): 'light' | 'dark' {
return this.theme as 'light' | 'dark'
},
typedUser(): User {
return this.user as User
}
},
mounted() {
console.log(this.typedTheme)
console.log(this.typedUser.name)
}
})
Why This Happens
The Options API inject array syntax inject: ['theme'] doesn't provide type information to TypeScript. Vue knows about the injection at runtime, but TypeScript's static analysis can't trace the provide/inject relationship across components.