Property Decorators
In this page:
Basic Field Decorator
A field decorator runs once when the class field is defined and can read or transform the field's initial value before any instance is created, giving you a hook into how that property starts out.
Example: Basic Field Decorator
function logged(value: undefined, context: ClassFieldDecoratorContext) {
console.log(`Field ${String(context.name)} is being defined`);
}
class User {
@logged
name = "Ravi";
}
new User();
Transforming Initial Values
Because the decorator sees the field's initializer function, it can wrap it to normalize or validate the starting value, such as trimming a string or clamping a number, before the property is ever assigned.
Example: Transforming Initial Values
function trimmed(value: undefined, context: ClassFieldDecoratorContext) {
return function (this: any, initial: string) {
return initial.trim();
};
}
class Form {
@trimmed
username = " Ravi ";
}
console.log(new Form().username);
Field Decorator Initializers
The decorator receives the class's field initializer as an argument, so returning a new initializer function lets you completely swap out how the field's default value is computed.
Example: Field Decorator Initializers
function withDefault(defaultValue: number) {
return function (value: undefined, context: ClassFieldDecoratorContext) {
return function (this: any, initial: number) {
return initial ?? defaultValue;
};
};
}
class Settings {
@withDefault(10)
volume = 10;
}
console.log(new Settings().volume);
Field Decorator Factories
A field decorator factory accepts arguments at the point of use, so the same decorator can enforce a different rule per field, like a minimum length for one string field and a different one for another.
Example: Field Decorator Factories
function minLength(min: number) {
return function (value: undefined, context: ClassFieldDecoratorContext) {
return function (this: any, initial: string) {
if (initial.length < min) throw new Error(`Too short, need ${min}`);
return initial;
};
};
}
class Account {
@minLength(3)
username = "Ravi";
}
console.log(new Account().username);
Static and Instance Fields
TypeScript's decorator metadata distinguishes between static fields (attached to the class itself) and instance fields (attached to each object), and a decorator needs to check which kind it's decorating before assuming shared state.
Example: Static and Instance Fields
function describe(value: undefined, context: ClassFieldDecoratorContext) {
console.log(`${String(context.name)} is ${context.static ? "static" : "instance"}`);
}
class Counter {
@describe
static total = 0;
@describe
count = 0;
}
new Counter();
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: