Лучший подход для сужения фабричного типа возврата без прохождения в классе - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь найти лучший подход для сужения возвращаемого типа фабрики, не передавая сам класс.Ниже приведен пример использования условных типов, который является лучшим подходом, который я нашел до сих пор.Есть ли более чистый способ сузить тип возвращаемого значения?

Настройка

class Lion {
  run() {
    // Do something
  }
}

class Fish {
  swim() {
    // Do something
  }
}

class Snake {
  slither() {
    // Do something
  }
}

enum AnimalType {
  LION = 'lion',
  FISH = 'fish',
  SNAKE = 'snake',
}

В этом примере возвращается тип объединения, который мне не нужен

class AnimalFactory {
  public static create(type: AnimalType) {
    switch (type) {
      case AnimalType.LION:
        return new Lion();
      case AnimalType.FISH:
        return new Fish();
      case AnimalType.SNAKE:
        return new Snake();
      default:
        throw new Error('Invalid Type');
    }
  }
}

const fish = AnimalFactory.create(AnimalType.FISH); // Type: Lion | Fish | Snake :(

В этом примере возвращается правильный тип, но, похоже, много накладных расходов

type Animal<T> = T extends AnimalType.LION
  ? Lion
  : T extends AnimalType.FISH
  ? Fish
  : T extends AnimalType.SNAKE
  ? Snake
  : unknown;

class AnimalFactory {
  public static create<T extends AnimalType>(type: T): Animal<T> {
    switch (type) {
      case AnimalType.LION:
        return new Lion() as Animal<T>;
      case AnimalType.FISH:
        return new Fish() as Animal<T>;
      case AnimalType.SNAKE:
        return new Snake() as Animal<T>;
      default:
        throw new Error('Invalid Type');
    }
  }
}

const fish = AnimalFactory.create(AnimalType.FISH); // Type: Fish :)

Есть ли более чистый способ сузить возврат к заводским значениямвведите только аргумент AnimalType?

1 Ответ

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

Вам нужен тип, который описывает, какой тип класса возвращается для какого значения перечисления:

interface AnimalFactoryReturnType {
  [AnimalType.LION]: Lion;
  [AnimalType.FISH]: Fish;
  [AnimalType.SNAKE]: Snake;
}

Затем вы можете использовать keyof, чтобы выбрать его:

class AnimalFactory {
  public static create<T extends keyof AnimalFactoryReturnType>(type: T): AnimalFactoryReturnType[T] {
    switch (type) {
      case AnimalType.LION:
        return new Lion();
      case AnimalType.FISH:
        return new Fish();
      case AnimalType.SNAKE:
        return new Snake();
      default:
        throw new Error('Invalid Type');
    }
  }
}

const fish = AnimalFactory.create(AnimalType.FISH); // Type: Fish :)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...