2017-07-18 40 views
3

我正在创建一个'Serializable'抽象类,我可以用一个以json对象作为参数的方法调用来创建子类。我用它来处理下面的代码,但它会导致一个相当笨拙的解决方案。是否有一种干净的方式在TypeScript中创建静态可继承的泛型构造函数?

我当前的代码:

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

我现在可以创建员工的新实例是这样的:

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

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

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

我觉得应该有一种方法,不必在一行中写入“员工”三次,而是取代任何用'输入'这个'已经让我无处可去。 我意识到这可能通过不使构造静态的,而是有两条线来避免:

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

但是,如果有任何清洁的方式在同一行要做到这一点,我将不胜感激一个例子!我不完全理解ctor: { new(): T}论点的作用,所以我对解决方案的无知可能源于此。

回答

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 

注意到出现了铸件的thisany,这是必要的,因为Serializable是抽象的,所以编译器抱怨说,它不能被实例化。
如果你删除了抽象部分,那么你也可以删除这个类型。

而且,没有必要遍历这样的属性,你可以简单地使用Object.assign

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

那正是我所想象的。我对TS有点新,所以我不得不在这个语法上做一些搜索,但问题解决了。谢谢! –

+0

你想了解哪些部分?我可以送你正确的方向。 –

+0

我想我的问题是找到一种方法来获取调用该方法的子类的类型。你通过 提供了这个:{new():T} 它是否自动传递一个对象实例作为第一个参数? 编辑:也道具减少整个功能,以一条线,如果我可以upvote这两次,我会。 –

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

如果你不能重写抽象类,那么你就不得不像你已经做过的那样使用它。

+1

完全不得要领。这个想法(据我了解)是能够反序列化不同的类,而不仅仅是'Employee'。另外,'jsonString'不是**类型的**。 –

+0

我同意。无论如何,我确信他无法重构课程,所以他仍然不得不像他已经做到的那样使用它。 –

+0

实际上他有一个简单的解决方案,他试图做的事情。检查我的答案 –

相关问题