TypeScript:通用 class 实现的包装器

TypeScript: wrapper for generic class implementation

为什么在 TypeScript 中不能执行以下操作?

abstract class Generic<T> {
  // ...
}

class Specific1 extends Generic<string> {
  // ...
}

class Specific2 extends Generic<number> {
  // ...
}

// this is where stuff goes wrong, compiler wants me to provide generic type arguments
//                                     |
//                                     ˅
abstract class Wrapper<T extends Generic> {
  // ...
}

class Wrapper1 extends Wrapper<Specific1> {
  // ...
}


class Wrapper2 extends Wrapper<Specific2> {
  // ...
}

对于 Wrapper 泛型 class 行,我试图表达我只想让 classes 进入 Wrapper 作为泛型类型,“具体实施”Generic,即 Specific1Specific2,在这种情况下。

在我正在进行的项目中,Generic 的泛型类型比此处显示的更多,实现也更多,即更多 SpecificX classes。我可以通过将所有泛型类型传递给之前传递给 SpecificXWrapperX 来避免这个问题,如下所示:

class Specific1 extends Generic<type1, type2, type3> {
  ...
}

...

class Wrapper1 extends Wrapper<type1, type2, type3> {
  ...
}

...但是我就是觉得很脏,我想知道是否有更好的方法来解决这个问题。我已经定义了我的 SpecificX class 及其通用类型,并希望避免在不同的位置再次这样做。

简单的 DRY,但我不知道如何在 TypeScript 中做到这一点:(

如果 Wrapper 应该能够 包装任何 Generic,而您并不关心实际的 Specific type 可能是,然后将类型参数显式标记为 unknown 就可以做到这一点。使用以下内容,您可以为扩展 Generic.

的任何内容创建包装器
abstract class Wrapper<T extends Generic<unknown>>

如果 Wrapper 应该只 包装 Specific 类型之一 ,那么您可以使用 union type 来解决这个问题。创建一个包含所有选项的新类型可能是个好主意。这肯定更冗长,但可以防止任何任意内容(例如 Generic<ButNotASpecificType>)被包装。

class Specific1 extends Generic<string> {
  // ...
}

class Specific2 extends Generic<number> {
  // ...
}

type Specific = Specific1 | Specific2

abstract class Wrapper<T extends Specific>

这里 TypeScript playground link 展示了这两种方法。