使用 switch 语句缩小泛型类型范围无效。

3

我试图缩小枚举类型的范围,并根据枚举值返回不同的类实例。

为什么在没有使用泛型时 switch case 能够正常工作?

在示例1中,我尝试缩小扩展枚举的泛型类型的范围。然而,当我使用 switch 语句时仍会出错。

在示例2中,直接缩小枚举类型的范围不会导致错误。

这背后有什么理由吗?

class ReportA {
   constructor(public type: ReportType.A) { }
}

class ReportB {
   constructor(public type: ReportType.B) { }
}

enum ReportType {
   A = "A",
   B = "B"
}

/** Example 1. Does not work... Why? */
class ReportFactory<Type extends ReportType> {
   constructor(public type: Type) { }

   public create = () => {
      switch (this.type) {
         case ReportType.A: {
            /** ERROR! */
            return new ReportA(this.type)
         }
         case ReportType.B: {
            /** ERROR! */
            return new ReportB(this.type)
         }
         default: throw new Error()
      }
   }
}

/** Example 2. Works */
class ReportFactory2 {
   constructor(public type: ReportType) { }
 
   public create = () => {
      switch (this.type) {
         case ReportType.A: {
            /** WORKS! */
            return new ReportA(this.type)
         }
         case ReportType.B: {
            /** WORKS! */
            return new ReportB(this.type)
         }
         default: throw new Error()
      }
   }
}


这里是 Playground


1
顺便说一句,如果 ReportFactory2 也是一个 class,那么唯一的区别就是泛型参数,会更清晰一些,像这样:https://pastebin.com/iPYXqCF7 关于实际问题,我不明白为什么 TypeScript 不允许那样做——可能与 extends 有关,但是... 当然,你可以使用字面值 (case ReportType.A: { /** Works now */ return new ReportA(ReportType.A) }),但是标签和参数之间的重复很烦人,而且(在我看来)是一个维护问题... :-| - T.J. Crowder
1
@T.J.Crowder 谢谢您的建议。我已经根据它编辑了我的示例。 - Ramil Amparo
2
似乎与https://github.com/microsoft/TypeScript/issues/13995有关。 - Yury Tarabanko
1个回答

0

这似乎是 TypeScript 的一个问题。感谢@Yury Tarabanko的链接。

看起来对我唯一的解决方案就是强制类型转换或使用// @ts-ignore注释。

new ReportA(this.type as ReportType.A)
// @ts-ignore
new ReportA(this.type)

最好尝试使用TypeScript守卫 https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types - captain-yossarian from Ukraine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接