возможно ли вычислить свойства класса динамически по полученным аргументам конструктора? - PullRequest
2 голосов
/ 30 мая 2020

В основном я хочу объединить эти два класса:

class ResponseDto

export class ResponseDto<T = Record<string, any>>  {
    public readonly sucess = true;

    constructor(
        public data: T
    ) { }
}

class IterableResponseDto

export class IterableResponseDto<T = Record<string, any>[]> {
    public readonly sucess = true;

    constructor(
        public data: T,
        public paging: Paging
    ) { }
}

Как видите, когда data аргумент - это массив, вы можете предоставить аргумент paging типа certan, в противном случае только data может быть обязательным.

1 Ответ

1 голос
/ 30 мая 2020

Вы могли бы использовать условный тип для представления типа кортежа остальных аргументов для конструктора:

export class ResponseDto<T extends Record<string, any> | Array<Record<string, any>>>  {
  public readonly sucess = true;
  public paging: Paging | undefined;

  constructor(
    public data: T,
    ...[paging]: (T extends Array<any> ? [Paging] : [])
  ) {
    this.paging = paging;
  }

}

Выше paging аргумент будет принят тогда и только тогда, когда тип T является массивом. Внутри реализации класса свойство paging установлено на Paging | undefined. Может оказаться трудным, чтобы реализация класса знала, когда Paging присутствует, а когда нет, так как компилятору сложно рассуждать об условных типах, которые зависят от неуказанных универсальных шаблонов.

Но, по крайней мере, со стороны вызывающего абонента это должно работать, как ожидалось:

declare const paging: Paging;

const okayObject = new ResponseDto({ a: "hello" });
const badObject = new ResponseDto({ a: "hello" }, paging); // error!
// expected 1 arg, got 2

const okayArray = new ResponseDto([1, 2, 3], paging);
const badarray = new ResponseDto([1, 2, 3]); // error!
// expected 2 args, got 1

Хорошо, надеюсь, это поможет; удачи!

Детская площадка ссылка на код

...