打字稿:在静态方法中使用子类 [英] Typescript: Work with Child Class in static method

查看:51
本文介绍了打字稿:在静态方法中使用子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 TypeScript(我使用了 Playground, version 4.13)中,当我从一个类继承时,父类的 static 方法中的 this 似乎是指继承类:

In TypeScript (I used the Playground, version 4.13) , when I inherit from a class, this inside a static method of the parent class seems to refer to the inheriting 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

但是,当我想根据子类的类型定义一些行为时遇到了问题:

However, I am having problems when I want to define some behavior depending on the type of the 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)

这给了我

元素隐式具有any"类型,因为string"类型的表达式 |数量 |符号'不能用于索引类型'typeof Parent'.在typeof Parent"类型上找不到参数为string"类型的索引签名.

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 类型转换为子类的键来解决这个问题:

I tried to go round this problem, by typecasting the key as a key of the 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)

但这是被禁止的.我得到

But this is forbidden. I get

this"类型仅在类或接口的非静态成员中可用

A 'this' type is available only in a non-static member of a class or interface

另外,我得到(在所有情况下)

Also, I get (in all scenarios)

属性id"在类型Parent"上不存在.

Property 'id' does not exist on type 'Parent'.

如何解决我的问题 - 从对象(我在现实世界中从 API 接收)动态填充子类的属性?

How can I solve my problem - dynamically populate the properties of the child class from an object (which I receive from an API in my real-world scenario)?

推荐答案

您可以通过指定与类本身相对应的 this 参数来实现此目的.在静态方法中,this 指的是类本身.

You can accomplish this by specifying a this parameter corresponding to the class itself. In a static method, this refers to the class itself.

static create<T extends Parent>(this: new (...args: any[]) => T, data: object) {...} 

这里发生的事情是我们说的是 this 类型,它将引用包含该方法的对象,在这种情况下,无论 create 是什么类对象调用,可以返回类的实例类型的子类型.这是通过类型参数 T 以及类对象将具有返回 T 的构造签名的属性来实现的,从而捕获任何派生类的实例类型.

What's going on here is that we are saying that the this type, which will refer to the object containing the method, in this case whatever class object that create is called on, can return a subtype of the instance type of the class. This is accomplished via the type parameter T, and the ascription that the class object will have a construct signature that returns a T, thus capturing the instance type of any derived 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方法,通过如下调整create来提高类型安全性:

Since we have captured the derived instance type via T, we can refine the create method further to improve type safety by adjusting create as follows:

static create<T extends Parent>(this: new (...args: any[]) => T, data: Partial<T>) {...}

这可以防止我们在提供智能感知的同时传递,从而将任意属性分配给由 create 方法创建的对象.

This prevents us from passing, and thus assigning arbitrary properties to objects created by the create method while providing intellisense.

完整代码:

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);

游乐场链接

这篇关于打字稿:在静态方法中使用子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆