是否有一种在TypeScript中创建静态可继承通用构造函数的简洁方法?

时间:2017-07-18 13:01:44

标签: angular typescript

我正在制作一个可序列化的'抽象类,我可以使用以json对象作为参数的方法调用创建的子代。我让它使用以下代码,但它导致了一个相当笨拙的解决方案。

我目前的代码:

abstract class Serializable {
    public static deserialize<T>(jsonString: string, ctor: { new (): T}) {
        const newCtor = new ctor;
        const jsonObject = JSON.parse(jsonString);
        for (const propName of Object.keys(jsonObject)) {
            newCtor[propName] = jsonObject[propName]
        }
        return newCtor;
    }

    public static deserializeList<T>(jsonString: string, ctor: { new (): T}) {
        let newCtor = new ctor;
        const newArray = new Array<typeof newCtor>();
        const jsonArray = JSON.parse(jsonString)['staff'];
        for (const jsonObject of jsonArray) {
            newCtor = new ctor;
            for (const propName of Object.keys(jsonObject)) {
                newCtor[propName] = jsonObject[propName]
            }
            newArray.push(newCtor);
        }
        return newArray;
    }
}

export class Employee extends Serializable {
    firstName: string;
    lastName: string;
}

我现在可以像这样创建一个新的Employee实例:

const testJson = '{"firstName": "Max", "lastName": "Mustermann"}';
const testEmployee = Employee.deserialize<Employee>(testJson, Employee);

理想情况下,我希望能够做到这一点:

const testJson = '{"firstName": "Max", "lastName": "Mustermann"}';
const testEmployee = Employee.deserialize(testJson);

我觉得应该有办法不必写“员工”。在一行中三次,但用“&#39;类型替换任何东西&#39;让我无处可去。 我意识到这可以通过不使构造函数静态来避免,而是有两行:

const testJson = '{"firstName": "Max", "lastName": "Mustermann"}';
const testEmployee = new Employee();
testEmployee.deserialize(testJson);

但如果有任何干净的方法在一行中做到这一点,我会很感激一个例子!我不完全理解ctor: { new (): T}论证的作用,所以我对解决方案的无知可能源于此。

2 个答案:

答案 0 :(得分:3)

是的,你可以这样做:

abstract class Serializable {
    public static deserialize<T>(this: { new(): T }, jsonString: string): T {
        const newCtor = new (this as any)();
        ...
    }
}

const testEmployee = Employee.deserialize2(testJson); // type of testEmployee is Employee

请注意,由于this是抽象的,所以需要将any转换为Serializable,因此编译器会抱怨它无法实例化。<登记/> 如果你删除抽象部分,那么你也可以删除这个演员。

此外,没有必要迭代这样的属性,您只需使用Object.assign

public static deserialize<T>(this: { new (): T }, jsonString: string): T {
    return Object.assign(new (this as any)(), JSON.parse(jsonString));
}

答案 1 :(得分:0)

关于类型。

  abstract class Serializable {
    public static deserialize(jsonString: Employee) {
        const newCtor = new Employee();
        const jsonObject = JSON.parse(jsonString);
        for (const propName of Object.keys(jsonObject)) {
            newCtor[propName] = jsonObject[propName]
        }
        return newCtor;
    }

    public static deserializeList(jsonString: Employee) {
        let newCtor = new Employee();
        const newArray: Employee[] = [];
        const jsonArray = JSON.parse(jsonString)['staff'];
        for (const jsonObject of jsonArray) {
            newCtor = new ctor;
            for (const propName of Object.keys(jsonObject)) {
                newCtor[propName] = jsonObject[propName]
            }
            newArray.push(newCtor);
        }
        return newArray;
    }
}

如果你不能重写抽象类,那么你就不得不像以前那样使用它。