打字稿:在静态方法中使用 Child Class
Typescript: Work with Child Class in static method
在 TypeScript(我使用 Playground,版本 4.13)中,当我从 class 继承时,this
在 [=48 的 static
方法中=] class 好像是指继承 class:
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
但是,当我想根据 child class:
的类型定义一些行为时,我遇到了问题
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)
这给了我
Element implicitly has an 'any' type because expression of type 'string | number | symbol' can't be used to index type 'typeof Parent'. No index signature with a parameter of type 'string' was found on type 'typeof Parent'.
我试图通过将 key
类型转换为 child class:
的键来解决这个问题
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)
但这是被禁止的。我得到
A 'this' type is available only in a non-static member of a class or interface
此外,我得到(在所有情况下)
Property 'id' does not exist on type 'Parent'.
我该如何解决我的问题 - 从 object 动态填充 child class 的属性(我从我的 real-world场景)?
您可以通过指定与 class 本身相对应的 this
参数来完成此操作。在静态方法中,this
指的是 class 本身。
static create<T extends Parent>(this: new (...args: any[]) => T, data: object) {...}
这里发生的事情是我们说 this
类型,它将引用包含该方法的对象,在这种情况下,create
是什么 class 对象在调用时,可以 return 实例类型的子类型 class。这是通过类型参数 T
实现的,class 对象将具有 return 一个 T
的构造签名,从而捕获任何派生的实例类型class.
这是完整的工作代码:
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
方法,通过调整创建来提高类型安全性,如下所示:
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);
在 TypeScript(我使用 Playground,版本 4.13)中,当我从 class 继承时,this
在 [=48 的 static
方法中=] class 好像是指继承 class:
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
但是,当我想根据 child class:
的类型定义一些行为时,我遇到了问题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)
这给了我
Element implicitly has an 'any' type because expression of type 'string | number | symbol' can't be used to index type 'typeof Parent'. No index signature with a parameter of type 'string' was found on type 'typeof Parent'.
我试图通过将 key
类型转换为 child class:
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)
但这是被禁止的。我得到
A 'this' type is available only in a non-static member of a class or interface
此外,我得到(在所有情况下)
Property 'id' does not exist on type 'Parent'.
我该如何解决我的问题 - 从 object 动态填充 child class 的属性(我从我的 real-world场景)?
您可以通过指定与 class 本身相对应的 this
参数来完成此操作。在静态方法中,this
指的是 class 本身。
static create<T extends Parent>(this: new (...args: any[]) => T, data: object) {...}
这里发生的事情是我们说 this
类型,它将引用包含该方法的对象,在这种情况下,create
是什么 class 对象在调用时,可以 return 实例类型的子类型 class。这是通过类型参数 T
实现的,class 对象将具有 return 一个 T
的构造签名,从而捕获任何派生的实例类型class.
这是完整的工作代码:
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
方法,通过调整创建来提高类型安全性,如下所示:
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);