Parameter Properties

Parameter Properties — синтаксический сахар TypeScript в конструкторах классов: модификаторы public, private, protected, readonly перед параметром конструктора автоматически создают одноимённое свойство класса и присваивают ему переданное значение.

Зачем нужно

Убирают бойлерплейт: без parameter properties нужно объявить поле, принять его параметром, присвоить в теле. С ними — всё в одну строку. Особенно полезно в dependency injection, DTO и value objects.

Где используется

  • Простые сервисы и классы-обёртки
  • DTO и value objects
  • Dependency injection (NestJS, InversifyJS)
  • Классы с несколькими readonly-полями

Основной контент

До и после Parameter Properties

// Без parameter properties — 9 строк
class UserService {
  private readonly userRepo: UserRepository;
  private readonly logger: Logger;

  constructor(userRepo: UserRepository, logger: Logger) {
    this.userRepo = userRepo;
    this.logger   = logger;
  }
}

// С parameter properties — 4 строки
class UserService {
  constructor(
    private readonly userRepo: UserRepository,
    private readonly logger: Logger,
  ) {}
}

Доступные модификаторы

class Example {
  constructor(
    public    publicProp: string,         // доступно снаружи
    private   privateProp: number,        // только внутри класса
    protected protectedProp: boolean,     // класс + наследники
    readonly  readonlyProp: Date,         // публичный + только чтение
    public readonly id: string,           // явно публичный + readonly
  ) {}
}

const e = new Example("a", 1, true, new Date, "u-1");
console.log(e.publicProp);   // OK
console.log(e.readonlyProp); // OK
// e.privateProp;              // Error
// e.readonlyProp = new Date(); // Error — readonly

Комбинирование с обычными параметрами

class Parser {
  constructor(
    public readonly format: string,
    rawInput: string,  // обычный параметр — НЕ становится свойством
  ) {
    console.log(rawInput.trim()); // доступен в конструкторе
  }
}

const p = new Parser("json", "  data  ");
// p.format — OK
// p.rawInput — Error (свойства нет)

Parameter properties с наследованием

class Animal {
  constructor(public name: string) {}
}

class Dog extends Animal {
  constructor(
    name: string,
    public breed: string,
  ) {
    super(name); // super обязателен
  }
}

const dog = new Dog("Rex", "Labrador");
console.log(dog.name);  // "Rex"
console.log(dog.breed); // "Labrador"

Dependency Injection (NestJS-стиль)

class OrderService {
  constructor(
    private readonly orderRepo: OrderRepository,
    private readonly emailService: EmailService,
    private readonly logger: Logger,
  ) {}

  async createOrder(data: CreateOrderDto): Promise<Order> {
    const order = await this.orderRepo.save(data);
    await this.emailService.sendConfirmation(order);
    this.logger.log(`Order ${order.id} created`);
    return order;
  }
}

Частые ошибки

  • Забыть super при наследовании — конструктор подкласса обязан вызвать super(...) до использования this.
  • Обычный параметр без модификатора как свойство — параметр без public/private/protected/readonly не создаёт свойство.
  • Изменить readonly-поле в методе — компилятор выдаст ошибку; используйте private если нужна мутация.
  • Использовать в не-конструкторах — parameter properties работают только в constructor, не в обычных методах.

Связанные темы

Ресурсы