【发布时间】:2020-11-26 12:40:07
【问题描述】:
用例:我想为特定类(Model 类)实例的查找表(Table 类)建模一个通用系统。
我想做的一个最小的例子:
// Generic part
abstract class Table<T extends Model> {
instances: Map<number, T> = new Map();
}
abstract class Model {
constructor(
public readonly id: number,
public table: Table<this> // Error
) {
table.instances.set(id, this);
}
}
// Example: a table of Person objects
class Person extends Model {
constructor(
id: number,
table: Table<this>, // Error
public name: string
) {
super(id, table);
}
}
class PersonTable extends Table<Person> {}
const personTable = new PersonTable();
const person = new Person(0, personTable, 'John Doe');
// Note: the idea of using `this` as generic type argument is to guarantee
// that other models cannot be added to a table of persons, e.g. this would fail:
// class SomeModel extends Model { prop = 0; }
// const someModel = new SomeModel(1, person.table);
// ^^^^^^^^^^^^
不幸的是,TypeScript 抱怨构造函数中的 this 类型。为什么不允许这样做?有没有更好的方法来做到这一点?
不安全的替代方案
目前我正在使用以下 unsafe 替代方案。
// Generic part
abstract class Table<T extends Model> {
instances: Map<number, T> = new Map();
}
abstract class Model {
public table: Table<this>;
constructor(
public readonly id: number,
table: Table<Model>
) {
table.instances.set(id, this);
this.table = table as Table<this>;
}
}
// Example: a table of Person objects
class Person extends Model {
constructor(
id: number,
table: Table<Person>,
public name: string
) {
super(id, table);
}
}
class PersonTable extends Table<Person> {}
回复评论
回答 Liam 的评论:this 类型的一个非常简单的安全示例。
class A {
someInstances: this[] = [];
}
class B extends A {
someProp = 0;
}
const a = new A();
const b = new B();
a.someInstances.push(b);
// This isn't allowed: b.someInstances.push(a);
【问题讨论】:
-
Model是一个类型,this是一个类型的instance。所以它是无效的,你想要Table<Person>而不是Table<this> -
@Liam Polymorphic
thistypes -
在该链接中使用的
this中,它只是作为类型(: this)返回,而不是泛型类型(Type<this>)。所以我猜泛型不支持这种类型的类型。 -
@Liam 在泛型中支持,只是在构造函数中不支持。有关在合法场所使用的示例,请参阅我的“不安全替代方案”。
-
@Liam 对于使用 this 类型的 shrug 示例,请参阅我的编辑。
标签: javascript typescript generics types this