TypeScript decorators for Vue.js class-based components with property binding, state management, and lifecycle capabilities
—
Provide and Inject decorators for parent-child component communication and dependency injection patterns. These decorators implement Vue's provide/inject mechanism using class-based syntax, enabling dependency injection across component hierarchies.
Provides dependency injection values to child components, making values available to descendant components in the component tree.
/**
* Provides dependency injection values to child components
* @param key - Injection key (optional, defaults to property name)
* @returns Property decorator function
*/
function Provide(key?: string | symbol): PropertyDecorator;Usage Examples:
import { Vue, Component, Provide } from "vue-property-decorator";
@Component
export default class ParentComponent extends Vue {
// Provide with default key (property name)
@Provide()
message = "Hello from parent";
// Provide with custom key
@Provide("customKey")
customData = { value: 42 };
// Provide with symbol key
private static THEME_KEY = Symbol("theme");
@Provide(ParentComponent.THEME_KEY)
theme = "dark";
// Provide computed value
@Provide("computedValue")
get computedValue() {
return `Computed: ${this.message}`;
}
}Provides reactive dependency injection values to child components, ensuring that changes in parent values automatically update in child components.
/**
* Provides reactive dependency injection values to child components
* @param key - Injection key (optional, defaults to property name)
* @returns Property decorator function
*/
function ProvideReactive(key?: string | symbol): PropertyDecorator;Usage Examples:
import { Vue, Component, ProvideReactive } from "vue-property-decorator";
@Component
export default class ReactiveParent extends Vue {
// Reactive provide - children will update when this changes
@ProvideReactive()
counter = 0;
// Reactive provide with custom key
@ProvideReactive("sharedState")
state = {
user: null,
isLoggedIn: false
};
increment() {
this.counter++; // All injected children will receive the new value
}
login(user: any) {
this.state.user = user;
this.state.isLoggedIn = true; // Children will reactively update
}
}Injects dependencies from parent components, receiving values provided by ancestor components in the component tree.
/**
* Injects dependencies from parent components
* @param options - InjectOptions object or InjectKey (optional, defaults to property name)
* @returns Property decorator function
*/
function Inject(options?: InjectOptions | InjectKey): PropertyDecorator;
interface InjectOptions {
from?: InjectKey;
default?: any;
}
type InjectKey = string | symbol;Usage Examples:
import { Vue, Component, Inject } from "vue-property-decorator";
@Component
export default class ChildComponent extends Vue {
// Inject with default key (property name)
@Inject()
message!: string;
// Inject with custom key
@Inject("customKey")
customData!: { value: number };
// Inject with default value
@Inject({ default: "fallback" })
optionalMessage!: string;
// Inject with different key and default
@Inject({ from: "parentTheme", default: "light" })
theme!: string;
// Inject symbol key
@Inject(Symbol.for("global-config"))
config!: any;
}Injects reactive dependencies from parent components, automatically updating when parent provided values change.
/**
* Injects reactive dependencies from parent components
* @param options - InjectOptions object or InjectKey (optional, defaults to property name)
* @returns Property decorator function
*/
function InjectReactive(options?: InjectOptions | InjectKey): PropertyDecorator;Usage Examples:
import { Vue, Component, InjectReactive, Watch } from "vue-property-decorator";
@Component
export default class ReactiveChild extends Vue {
// Reactive inject - will update when parent changes the value
@InjectReactive()
counter!: number;
// Reactive inject with custom configuration
@InjectReactive({ from: "sharedState", default: null })
state!: { user: any; isLoggedIn: boolean } | null;
// Watch reactive injected values
@Watch("counter")
onCounterChanged(newVal: number, oldVal: number) {
console.log(`Counter changed from ${oldVal} to ${newVal}`);
}
@Watch("state", { deep: true })
onStateChanged(newState: any) {
if (newState && newState.isLoggedIn) {
console.log("User logged in:", newState.user);
}
}
}// Provider component
@Component
export default class DataProvider extends Vue {
@ProvideReactive("dataService")
dataService = {
items: [],
loading: false,
async fetchItems() {
this.loading = true;
try {
this.items = await api.getItems();
} finally {
this.loading = false;
}
}
};
}
// Consumer component
@Component
export default class DataConsumer extends Vue {
@InjectReactive("dataService")
dataService!: any;
mounted() {
this.dataService.fetchItems();
}
}// App root component
@Component
export default class App extends Vue {
@Provide("appConfig")
config = {
apiUrl: process.env.VUE_APP_API_URL,
theme: "default",
features: {
darkMode: true,
notifications: true
}
};
}
// Deeply nested component
@Component
export default class FeatureComponent extends Vue {
@Inject("appConfig")
config!: any;
get isDarkModeEnabled() {
return this.config.features.darkMode;
}
}interface InjectOptions {
from?: InjectKey;
default?: any;
}
type InjectKey = string | symbol;
type PropertyDecorator = (target: any, propertyKey: string | symbol) => void;Install with Tessl CLI
npx tessl i tessl/npm-vue-property-decorator