Рефакторинг JavaScript / TypeScript: устранение повторяющихся блоков кода - PullRequest
0 голосов
/ 28 марта 2019

Как я могу сократить этот монстр блок?(Не массив решение)

setFooTypeFlag(flag: string) {
  switch (flag) {
    case 'a':
      this.fooType.a = true;  
      this.fooType.b = false;
      this.fooType.c = false;
      this.fooType.d = false;
      break;
    case 'b'
      this.fooType.a = false;
      this.fooType.b = true;
      this.fooType.c = false;
      this.fooType.d = false;
      break;
    case 'c':
      this.fooType.a = false;
      this.fooType.b = false;
      this.fooType.c = true;
      this.fooType.d = false;
      break;
    case 'd':
      this.fooType.a = false;
      this.fooType.b = false;
      this.fooType.c = false;
      this.fooType.d = true;
      break;
  }
}

Ответы [ 4 ]

3 голосов
/ 28 марта 2019

Это достаточно коротко для вас? :)

В общем, итерируйте по каждому ключу и просто установите все на flag === key:)

setFooTypeFlag(flag: string) {
  Object.keys(this.fooType).forEach(key => {
      this.fooType[key] = flag === key;
  });
}

Если в начале у this еще нет ключей, обратитесь к ответу Джека .

1 голос
/ 29 марта 2019

Меня также вдохновил ответ от @ jack-bashford:

class MyClass {
  private flags = [...Array(26)].map((_, i) => (i + 10).toString(36));
  private minObjectKeys = 4;

  public buildBaseObject(flag: string): any {
    return this.getFlagPortion(flag).reduce(
      (obj, key) => ({ ...obj, [key]: key === flag }),
      {}
    );
  }

  private getFlagPortion(flag: string): string[] {
    const sliceEndPositon = this.getSliceEndPosition(flag);
    return this.flags.slice(0, sliceEndPositon);
  }

  private getSliceEndPosition(flag: string): number {
    const flagPosition = this.flags.indexOf(flag) + 1;
    return flagPosition < this.minObjectKeys
      ? this.minObjectKeys
      : flagPosition;
  }
}

const fooLover = new MyClass();
alert(JSON.stringify(fooLover.buildBaseObject("d")));

Вот демоверсия

1 голос
/ 28 марта 2019
enum fooTypes {
  "a" = "a",
  "b" = "b",
  "c" = "c",
  "d" = "d"
}

interface IFooFlags {
  [key: string]: boolean;
}

const defaultFooTypes = new Map<fooTypes, boolean>([
  [fooTypes.a, true],
  [fooTypes.b, true],
  [fooTypes.c, true],
  [fooTypes.d, true]
]);

const fooTypesMappings = new Map<fooTypes, boolean[]>([
  [fooTypes.a, [true, false, false, false]],
  [fooTypes.b, [false, true, false, false]],
  [fooTypes.c, [false, false, true, false]],
  [fooTypes.d, [false, false, false, true]]
]);

class MyClass {
  private mappings = fooTypesMappings;
  private fooTypes = defaultFooTypes;

  private setFooTypes(values: boolean[]): void {
    [...this.fooTypes.keys()].forEach((key, index) =>
      this.fooTypes.set(key, values[index])
    );
  }

  // In modern engines you can return:
  // Object.fromEntries(this.fooTypes)
  public getFooTypes(): IFooFlags {
    return [...this.fooTypes].reduce(
      (obj, { 0: key, 1: val }) => ({ ...obj, [key]: val }),
      {}
    );
  }

  public setFooTypeFlag(flag: fooTypes): void {
    const flagTypes = this.mappings.get(flag);
    if (!flagTypes) {
      throw new Error("Invalid flag type");
    }
    this.setFooTypes(flagTypes);
  }
}

const fooLover = new MyClass();
fooLover.setFooTypeFlag(fooTypes.d);
alert(JSON.stringify(fooLover.getFooTypes()));

Вот демонстрация этого

1 голос
/ 28 марта 2019

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

setFooTypeFlag(flag: string) {
  var chars = ["a", "b", "c", "d"];
  for (var i = 0; i < chars.length; i++) {
    this.fooType[chars[i]] = chars[i] == flag;
  }
}
...