在TypeScript(我使用了Playground,版本4.13)中,当我从类继承时,父类this
的static
方法内部似乎引用了继承的类:
class Parent{
static ID = 0
public id: number
static create(){
return new this(this.ID)
}
constructor(id: number){
this.id = id
}
}
class Child extends Parent{
static ID = 1
}
let child = Child.create()
console.log(child.id) // 1
但是,当我想根据子类的类型定义某些行为时遇到问题:
class Parent{
static create(data: object){
let instance = new this
for (let [key, value] of Object.entries(data)){
this[key] = value
}
return instance
}
}
class Child extends Parent{
id: number | null = null
}
let child = Child.create({id: 1})
console.log(child.id)
这给我
元素隐式具有“ any”类型,因为类型为'string | 编号| 符号”不能用于索引类型“父类型”。在“ typeof Parent”类型上未找到带有“ string”类型参数的索引签名。
我试图通过类型转换key
作为子类的键来解决这个问题:
class Parent{
static create(data: object){
let instance = new this
for (let [key, value] of Object.entries(data)){
this[key as keyof this] = value
}
return instance
}
}
class Child extends Parent{
id: number | null = null
}
let child = Child.create({id: 1})
console.log(child.id)
但这是被禁止的。我懂了
“此”类型仅在类或接口的非静态成员中可用
另外,我得到(在所有情况下)
属性“ id”在“父母”类型上不存在。
我该如何解决我的问题-从对象中动态填充子类的属性(在现实情况下是从API接收的)?
您可以通过指定this
与类本身相对应的参数来完成此操作。在静态方法中,this
指的是类本身。
static create<T extends Parent>(this: new (...args: any[]) => T, data: object) {...}
这里的意思是说this
类型将引用包含该方法的对象,在这种情况下,无论create
调用哪种类对象,该类型都可以返回该类的实例类型的子类型。这是通过type参数完成的T
,并且类对象将具有返回a的构造签名的说明T
,从而捕获了任何派生类的实例类型。
这是完整的工作代码:
class Parent {
static create<T extends Parent>(this: new (...args: any[]) => T, data: object) {
let instance = new this;
for (let [key, value] of Object.entries(data)) {
instance[key as keyof T] = value;
}
return instance;
}
}
class Child extends Parent {
id: number | null = null;
}
let child = Child.create({ id: 1 });
console.log(child.id);
由于我们已通过捕获了派生的实例类型T
,因此我们可以create
通过如下调整create来进一步完善该方法以提高类型安全性:
static create<T extends Parent>(this: new (...args: any[]) => T, data: Partial<T>) {...}
这样可以防止我们通过,从而create
在提供智能感知的同时将任意属性分配给由该方法创建的对象。
完整代码:
class Parent {
static create<T extends Parent>(this: new (...args: any[]) => T, data: Partial<T>) {
let instance = new this;
for (let [key, value] of Object.entries(data)) {
const k = key as keyof T;
instance[k] = value as T[typeof k];
}
return instance;
}
}
class Child extends Parent {
id: number | null = null;
}
let child = Child.create({ id: 1 });
console.log(child.id);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句