typescript 如何使用更具体的类属创建子类

rvpgvaaj  于 2022-11-30  发布在  TypeScript
关注(0)|答案(1)|浏览(134)

bounty将在6天后过期。回答此问题可获得+100声望奖励。sudoremo希望吸引更多人关注此问题。

在下面的代码中,我概述了两个问题(参见注解):
1.我需要一个静态方法来返回当前类的一个示例。当它在子类上被调用时(没有被覆盖),它应该返回子类的一个示例。
1.我需要一个泛型,以便在子类中更具体(Base应该取BaseOptions,而Sub应该取SubOptions,这是BaseOptions的超集)。
使用extends BaseOptions | SubOptions的解决方案对我不起作用,因为我无法列举所有可能的、更具体的选项类型来保持代码的通用性。
我是不是完全走错了路,还是有办法解决我的问题?

interface BaseOptions {
  a: string
}

interface SubOptions extends BaseOptions {
  a: string
  b: string
}

class Base<T extends BaseOptions> {
  options: T

  constructor(options: T) {
    this.options = options;
  }

  // Problem 1: When TypeScript is concerned, this method always returns an
  // instance of "Base", even when calling 'create' on a subclass (that does not
  // override 'create'). How can this be fixed?
  static create<T extends BaseOptions>(options: T): Base<T> {
    return new this(options);
  }
}

// Problem 2: Class 'Sub' requires more specific options than class 'Base', but
// TypeScript does not allow me to validate it:
//   2417: Class static side 'typeof Sub'
//         incorrectly extends base class static
//         side 'typeof Base'.
class Sub<T extends SubOptions> extends Base<T> {
  static create<T extends SubOptions>(options: T): Sub<T> {
    return new this(options);
  }
}
flvlnr44

flvlnr441#

interface IGenericMap<T> {
  [x: string]: T;
}
  
class Base<T extends IGenericMap<string>> {
  options: T

  constructor(options: T) {
    this.options = options;
  }

  static create<T extends IGenericMap<string>>(options: T): Base<T> {
    return new this(options);
  }
}

class Sub<T extends IGenericMap<string>> extends Base<T> {
  constructor(options: T) {
    super(options);
  }
}

console.log(Base.create({ a: 'one' }));
console.log(Sub.create({ a: 'one', b: 'two' }));

现在您可以正确地使用继承,create方法会返回适当的类。
如果在IGenericMap中使用对象Map而不是BaseOptionsSubOptions,则任何键都将具有可选择的通用值。在上面的示例中,字符串可以更改为任何其他类型:数字对象任何字符串|编号...

相关问题