← Back to TypeScript Course | Chapter 10: Decorators | Lesson 4 of 7

Property Decorators

Modern TypeScript uses field decorators to customize class fields. A field decorator receives the initial field value when instances are created and can return an initializer that transforms that value.

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

typescript
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

typescript
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

typescript
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

typescript
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

typescript
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:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.