Передать значение в метод по типу объекта union - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть класс для обработки данных, и данные могут быть из разных источников.Мне нужно передать источник, откуда данные должны быть получены.Итак, я хочу спросить, как правильно это сделать:

  • создать объект определенного интерфейса, который может быть расширен и, возможно, более понятен разработчику - processDataA
  • передать все в одну переменную и проверить источник по типу переменной - без кода и не так сложно - processDataB

  • использованиеотдельные переменные метода - не случай - мне нужно передать это значение через множество классов / опций в целевой класс

Пример:

interface DataProviderSource {
   dataURL?: string;
   dataArchive?: ArrayBuffer;
}

processDataA(source: DataProviderSource) {
   if (source.dataURL) {
      ...
   } else if (source.dataArchive) {
      ...
   } else {
      ...
   }
}

processDataB(source: ArrayBuffer | string) {
   if (source instanceof ArrayBuffer) {
      ...
   } else if (typeof source === "string") {
      ...
   } else {
     ...
   }
}

1 Ответ

0 голосов
/ 21 декабря 2018

Единственное, чего следует избегать, так это иметь слабые интерфейсы , подобные этому:

interface DataProviderSource {
   dataURL?: string;
   dataArchive?: ArrayBuffer;
}

, поскольку, поскольку каждое свойство является необязательным, оно позволяет передавать пустой объект.Мы не хотим этого - мы хотим, чтобы передавался ровно один формат данных.

Это вопрос вкуса.Один из возможных вариантов:

class Processor {
  static fromArrayBuffer(source: ArrayBuffer) {}
  static fromString(source: string) {}

  process(source: string | ArrayBuffer) {
    if (source instanceof ArrayBuffer) {
      return Processor.fromArrayBuffer(source);
    }

    return Processor.fromString(source);
  }
}

Это просто, но нарушает принцип открытия / закрытия.Вы также можете моделировать свои источники с помощью именованных конструкторов.В этой конструкции каждый тип источника оснащен собственным процессором.

interface Source<T = any> {
    data: T;
    process: () => void;
}

class DataURL implements Source<string> {
    constructor(readonly data: string) {
        this.data = data;
    };

    process() {}
}

class Archieve implements Source<ArrayBuffer> {
    constructor(readonly data: ArrayBuffer) {
        this.data = data;
    };

    process() {}
}

class SomeOther implements Source<string> {
    constructor(readonly data: string) {
        this.data = data;
    };

    process() {}
}

Это решение открыто для расширения.Единственное, что имеет значение для источника, это реализовать интерфейс Source.

const process = (...sources: Source[]): void =>
  sources.forEach(source => source.process())

process(
    new DataURL('hello'),
    new Archieve(new ArrayBuffer(32)),
    new SomeOther('world')
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...