Class-打字稿中的方法
Class-method in Typescript
我希望能够在 Typescript 中使用基于 class 的方法 - 即在基础 class 上定义的方法,当在子 class 上调用时,可以访问调用它的 subclass。这种行为在 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 方法而无法使用。
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 很容易做到这一点,但我想不出一种方法可以将这样的方法用于多个 classes,而无需重新在每个人身上宣布它。
附带问题:
有什么方法可以在每个子 class 上有一个 "objects" 静态 属性,每个都输入到它们的子class,而无需手动重新声明它。
class Model {
static objects: Model[]
class Foo extends Model {
static objects: Foo[]
class Bar extends Model {
static objects: Bar[]
本质上,我想要这种行为,但不必在每个子 class 上单独声明 "objects" 属性。有什么办法吗?
静态方法的 this
上下文是调用它的 class。您可以覆盖 getById
的 this
类型,以声明 getById
可以在 Model
的任何子 class 上调用(即任何具有构造签名的对象构造 Model
) 的子类型和 returns class 的实例类型。这是示例代码,假设所有子 classes 的所有对象都存储在单个 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;
}
}
}
请注意,这是不合理的,因为有人可以使用对应于 Bar
而不是 Foo
的 ID 调用 Foo.getById
。
如果你想为每个子class单独的objects
数组,你需要在每个子class中手动初始化数组(没有办法自动执行此操作), 改变Model
构造函数压入当前class 的objects
数组(声明后可以引用为this.constructor
),然后改变getById
在声明它必须存在后使用 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;
}
}
}
我希望能够在 Typescript 中使用基于 class 的方法 - 即在基础 class 上定义的方法,当在子 class 上调用时,可以访问调用它的 subclass。这种行为在 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 方法而无法使用。
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 很容易做到这一点,但我想不出一种方法可以将这样的方法用于多个 classes,而无需重新在每个人身上宣布它。
附带问题:
有什么方法可以在每个子 class 上有一个 "objects" 静态 属性,每个都输入到它们的子class,而无需手动重新声明它。
class Model {
static objects: Model[]
class Foo extends Model {
static objects: Foo[]
class Bar extends Model {
static objects: Bar[]
本质上,我想要这种行为,但不必在每个子 class 上单独声明 "objects" 属性。有什么办法吗?
静态方法的 this
上下文是调用它的 class。您可以覆盖 getById
的 this
类型,以声明 getById
可以在 Model
的任何子 class 上调用(即任何具有构造签名的对象构造 Model
) 的子类型和 returns class 的实例类型。这是示例代码,假设所有子 classes 的所有对象都存储在单个 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;
}
}
}
请注意,这是不合理的,因为有人可以使用对应于 Bar
而不是 Foo
的 ID 调用 Foo.getById
。
如果你想为每个子class单独的objects
数组,你需要在每个子class中手动初始化数组(没有办法自动执行此操作), 改变Model
构造函数压入当前class 的objects
数组(声明后可以引用为this.constructor
),然后改变getById
在声明它必须存在后使用 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;
}
}
}