typescript - Typescript Class inference with statics
问题描述
import { FilterQuery } from "mongodb";
abstract class Base<T extends Base<any>> {
public static async findOne<T extends Base<any>>(
this: new (...a: any[]) => T,
query: FilterQuery<T>
): Promise<T> {
console.log(this.getSomeString()); // currently: "getSomeString" dosnt exists on type "new (...a: any[]) => T"
// already tried "typeof T" - because "typeof" is not allowed on generics
// already tried https://stackoverflow.com/a/52358194/8944059 's static solution
// already tried "T" - which makes "this: any"
// and i tried various other things, which resulted in "await SomeExtendingClass" cannot be assigned to "this"
// Edit for @jcalz
console.log(this.someProtectedMethod()); // error "someProtectedMethod" does not exists on type "this"
return undefined;
}
public static getSomeString(): string {
this.someProtectedMethod(); // this would work
return "Hello";
}
// Edit for @jcalz
protected static someProtectedMethod() {
return "hello2";
}
}
class SomeExtendingClass extends Base<SomeExtendingClass> {
public someValue: string;
}
(async () => {
await SomeExtendingClass.findOne({ someValue: "hi" });
})();
this
目标是在能够调用它的同时拥有所有静态变量,同时new this(...args)
让(父类)的所有键都可以插入query
并且不必删除abstract
已经尝试过:
- https://stackoverflow.com/a/58037767/8944059
- https://stackoverflow.com/a/52358194/8944059的静态解决方案
PS:我不明白打字稿类型的大部分魔力,这就是我问的原因......
PPS:这是我需要的项目
解决方案
您的示例代码根本没有说明为什么您需要任何this
参数。例如,以下代码甚至可以使用protected
静态方法。默认类型this
只是typeof Base
:
import { FilterQuery } from "mongodb";
abstract class Base<T extends Base<any>> {
public static async findOne<T extends Base<any>>(
query: FilterQuery<T>
): Promise<T> {
console.log(this.getSomeString());
console.log(this.someProtectedMethod());
return undefined!; // <-- not a Promise
}
public static getSomeString(): string {
return "Hello";
}
protected static someProtectedMethod() {
return "hello2";
}
}
class SomeExtendingClass extends Base<SomeExtendingClass> {
public someValue: string = "123"; // needs initialization
}
(async () => {
await SomeExtendingClass.findOne({ someValue: "hi" });
})();
如果以上内容不足以满足您的用例,请编辑您的示例代码以显示一些中断的地方。大概有一些原因你需要首先添加一个this
参数;什么原因?
无论如何,希望有所帮助;祝你好运!
编辑:如果您需要this
在内部使用零参数进行构造findOne()
,并且不允许findOne()
在无法以这种方式构造的类上调用,您可以这样做:
abstract class Base<T extends Base<any>> {
public static async findOne<T extends Base<any>>(
this: typeof Base & (new () => any),
query: FilterQuery<T>
): Promise<T> {
console.log(this.getSomeString());
console.log(this.someProtectedMethod());
new this();
return null!;
}
public static getSomeString(): string {
return "Hello";
}
protected static someProtectedMethod() {
return "hello2";
}
}
Base.findOne(null!); // error, abstract
class SomeExtendingClass extends Base<SomeExtendingClass> {
public someValue: string = "123"; // needs initialization
}
SomeExtendingClass.findOne(null!); // okay
class InvalidExtendingClass extends Base<InvalidExtendingClass> {
constructor(x: string) {
super();
}
}
InvalidExtendingClass.findOne(null!); // error, requires an argument
如果您有其他要求(例如允许子类使用不同的构造函数参数),请告诉我。再次祝你好运!
推荐阅读
- c# - ASP.NET Core API 使用 JWT 不记名令牌进行身份验证
- python - 使用 python 将抓取的数据直接保存到 azure blob 存储
- razor - Syncfusion DateRangePicker 更改后回发值
- javascript - 隐藏 API 信息
- c# - 如何过滤具有最新日期的记录
- python-3.x - 如何使用带有 Boto3 的 Lambda 函数的日期验证器标签值过滤 rds 实例
- netsuite - 如何使用 suitescript 1.0 访问项目主记录的库存详细信息?
- google-cloud-platform - 如何使用 GCP Translation API 处理 BigQuery 中的表?
- regex - 使用 grep 搜索以不同“形状”书写的三个单词
- javascript - 在 RSK Regtest 上开发时如何提高块号?