Your clue is in the definition of deserializeObject. You can't use a type in an expression. Types are erased after compilation T will not exist at runtime. That is why deserializeObject has a second parameter that takes in the class as a constructor signature (the classReference parameter).
You can do the same, and take the class as an extra parameter:
export class JsonSerializable {
toJson(): any {
const jsonConvert = new JsonConvert();
jsonConvert.valueCheckingMode = ValueCheckingMode.ALLOW_NULL;
return jsonConvert.serialize(this);
}
static fromJson<T extends JsonSerializable>(data: any, classReference: {
new (): T;
}): T {
const jsonConvert = new JsonConvert();
jsonConvert.valueCheckingMode = ValueCheckingMode.ALLOW_NULL;
return jsonConvert.deserializeObject(data, classReference);
}
}
class MyClass extends JsonSerializable {
public f = ""
}
let a = JsonSerializable.fromJson({}, MyClass); // a is MyClass
Or if you don't mind invoking fromJson on the class that you want deserialize, you can use this (with an appropriate type annotation on for the this parameter):
export class JsonSerializable {
toJson(): any {
const jsonConvert = new JsonConvert();
jsonConvert.valueCheckingMode = ValueCheckingMode.ALLOW_NULL;
return jsonConvert.serialize(this);
}
static fromJson<T extends JsonSerializable>(this: new () => T, data: any): T {
const jsonConvert = new JsonConvert();
jsonConvert.valueCheckingMode = ValueCheckingMode.ALLOW_NULL;
return jsonConvert.deserializeObject(data, this);
}
}
class MyClass extends JsonSerializable {
public f = ""
}
let a = MyClass.fromJson({}); // a is MyClass