繁体   English   中英

如何编写返回子类实例的static方法

[英]How to write a static method that returns a subclass instance

我正在尝试创建一个抽象的 class Enum ,它有一堆 static 方法返回调用它们的 class 的实例。 我的问题是我不知道如何正确输入这些方法。

本质上,我希望 TypeScript 了解EnumSubclass.getFirstInstance()返回一个EnumSubclass实例,而不是一个Enum实例。

这是我迄今为止最好的尝试:

type InstanceOf<T> = T extends { prototype: infer R } ? R : never

const instances = {}

abstract class Enum {
    protected constructor(
        public readonly name: string,
    ){
        instances[name] = this
    }

    public static getInstances<T extends typeof Enum>(this: T): InstanceOf<T>[] {
        return Object.values(instances)
    }

    public static getFirstInstance<T extends typeof Enum>(this: T): InstanceOf<T> {
        // No warning here, TypeScript understands that this.getInstances exists
        return this.getInstances()[0]
    }
}


class Demo extends Enum {
    public static readonly FOO = new Demo('foo', true)

    protected constructor(
        name: string,
        public readonly bar: boolean,
    ){
        super(name)
    }
}

// The 'this' context of type 'typeof Demo' is not assignable to method's 'this' of type 'typeof Enum'.
//   Types of construct signatures are incompatible.
//     Type 'new (name: string, bar: boolean) => Demo' is not assignable to type 'abstract new (name: string) => Enum'.ts(2684)
const x: Demo = Demo.getFirstInstance()

显然 TypeScript 有一个问题,即Demo的构造函数与Enum的构造函数具有不同的签名,即使Enum甚至从未调用构造函数 - 它返回已经存在的实例。

我怎样才能说服 TypeScript 这不是一个错误?

PS:理想情况下,我想:

  1. protected构造函数而不public它们
  2. Enum的实现中进行正确的输入(例如,在this.getInstances()中不应有警告)

这是期待已久但尚未实现的功能。 #5863

所以暂时不可能。

这是可能的,只要您不关心构造函数。

首先,定义这些助手类型:

type InstanceOf<T> = T extends { prototype: infer R } ? R : never
type IgnoreConstructor<T> = Pick<T, keyof T> & {name: string}

// Replace `Enum` with your base class
type EnumSubclass = IgnoreConstructor<typeof Enum>

然后像这样编写您的 static 方法:

static myFunc<T extends EnumSubclass>(this: T): InstanceOf<T>

证明它有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM