打字稿中的类方法

史密斯

我希望能够在Typescript中使用基于类的方法-即在基类上定义的方法,该基类在子类上调用时可以访问从中调用它的子类。在Python中,这种行为是可能的,但据我所知TypeScript中没有类似的行为。在Typescript中复制此内容的最佳方法是什么?

示例(在Python中):

这个示例(用Python编写)演示了我可能想要做的事情。

# Base class
class Model:
    objects = []

    def __init__(self, objId):
        self.objId = objId

        Model.objects.append(self)

    @classmethod
    def getById(cls, objId):
        # Method can access subclass using "cls" parameter
        objects = [obj for obj in cls.objects if obj.objId == objId]
        if len(objects) > 0:
            return objects[0]
        else:
            print("error")

# Subclass
class Foo(Model):
    def __init__(self, objId, name):
        self.objId = objId
        self.name = name

        Foo.objects.append(self)

Foo(1, "foo")
Foo(3, "bar")

# Call method on subclass
foo = Foo.getById(1)
bar = Foo.getById(3)

print(foo.name)  # outputs "foo"
print(bar.name)  # outputs "bar"

Foo.getById(2)  # outputs "error"

打字稿(不起作用):

此示例显示了打字稿中的粗略等效项,但由于缺少类方法而无法使用。

class Model {
    static objects: Model[]

    id: number

    constructor (id) {
        this.id = id

        Model.objects.push(this);
    }

    // Here "cls" should refer to the class on which this method is called
    static getById (id): cls {
        let item = cls.objects.find(obj => obj.id == id);
        if (item === undefined) {
            console.log("error");
        } else {
            return item;
        }
    }
}

class Foo extends Model {
    name: string

    constructor (id, name) {
        super(id);

        this.name = name

        Foo.objects.push(this);
    }
}


new Foo(1, "foo");
new Foo(3, "bar");

// Here cls === Foo
let foo = Foo.getById(1);
let bar = Foo.getById(3);

console.log(foo.name);
console.log(bar.name);

Foo.getById(2)

显然,使用单个类很容易做到这一点,但是我想不出一种方法可以对多个类使用这样的方法,而无需在每个类上都重新声明。

附带问题:

有什么方法可以在每个子类上都有一个“对象”静态属性,而每个子类都必须输入其子类,而无需手动重新声明它。

class Model {
    static objects: Model[]

class Foo extends Model {
    static objects: Foo[]

class Bar extends Model {
    static objects: Bar[]

本质上,我想要这种行为,但是不必在每个子类上分别声明“ objects”属性。有什么办法吗?

马特·麦考森

this静态方法上下文是在其上调用的类。您可以覆盖要声明this类型,getById以声明getById可以在的任何子类上调用类型Model(即,具有构造签名的子对象的任何对象Model),并返回该类的实例类型。这是示例代码,假定所有子类的所有对象都存储在单个Model.objects数组中:

class Model {
    static objects: Model[]

    id: number

    constructor (id) {
        this.id = id

        Model.objects.push(this);
    }

    static getById<M extends Model>(
        this: { new(...args: any[]): M }, id): M {
        let item = Model.objects.find(obj => obj.id == id);
        if (item === undefined) {
            console.log("error");
        } else {
            return <M>item;
        }
    }
}

请注意,这是不合理的,因为有人可以Foo.getById使用与a对应的IDBar而不是与进行呼叫Foo

如果objects每个子类都需要一个单独的数组,则需要在每个子类中手动初始化该数组(无法自动执行此方法),更改Model构造函数以将其推入objects当前类数组中(您可以将其引用为this.constructor在声明它之后),然后在声明它必须存在之后更改getById为use this.objects

class Model {
    static objects: Model[]
    "constructor": {
        // This implementation is slightly unsound: the element type
        // is actually the instance type of the constructor.  At least
        // the interface provided is safe.
        objects: Model[]
    };

    id: number

    constructor (id) {
        this.id = id

        this.constructor.objects.push(this);
    }

    static getById<M extends Model>(
        this: { new(...args: any[]): M, objects: M[] }, id): M {
        let item = this.objects.find(obj => obj.id == id);
        if (item === undefined) {
            console.log("error");
        } else {
            return item;
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章