【问题标题】:Best Approach for narrowing factory return type without passing in class缩小工厂返回类型而不通过类的最佳方法
【发布时间】:2018-12-16 03:58:27
【问题描述】:

我正在尝试找到在不传入类本身的情况下缩小工厂返回类型的最佳方法。下面是一个使用条件类型的示例,这是迄今为止我发现的最好的方法。有没有更简洁的方法来缩小返回类型?

设置

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 参数来缩小工厂返回类型?

【问题讨论】:

    标签: typescript generics factory union-types


    【解决方案1】:

    您需要一个类型来描述为哪个枚举值返回哪个类类型:

    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 :)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 2021-07-28
      • 2021-04-09
      • 2018-07-01
      • 1970-01-01
      • 2018-08-27
      相关资源
      最近更新 更多