Description
Search Terms
reflection, deserialization, json to class
Suggestion
Make reflection as powerful as in C#.
Javascript lacks functionality for desrialization json into classes. So I wrote library (ts-serializable) for deserialization and serialization json into classes, with property type validation. But I ran into a problem that typescript generates incorrect reflection for union types. As result, I can't recognize the type of property, and I have to use auxiliary attributs (jsonProperty(String, null)).
Example:
class Demo {
@reflection
public propA : string = ""; // in reflection: metadata("design:type", String)
@reflection
public propB : string | null = null; // in reflection: metadata("design:type", Object) !!!
}
So I propose to introduce new object Type. Similar to Type object from C#. Which will generate reflection of typerscript.
class Type {
public name: string;
... other props and methods
}
class PrimitiveType extends Type {
public primitive: "string" | "number" | "booelaen" ... and other;
}
class InerfaceType extends Type {
public implementsInterfaces: InerfaceType[];
}
class ClassType<T> extends Type {
public extendsClass: ClassType<object>;
public implementsInterfaces: InerfaceType[];
public classConstructor: new (...args: Object[]) => T;
}
class UnionType extends Type {
public unions: Type[];
}
class Demo {
@reflection
public propA : string = "";
// in reflection: metadata("design:type", new PrimitiveType("string"))
@reflection
public propB : string | null = null;
// in reflection: metadata("design:type", new UnionType([new PrimitiveType("string"), new PrimitiveType("null")]))
}
As result, quality of reflection and possibility of code reuse will greatly increase.
I also suggest adding the @extractInterface decorator for classes, which will extract public interface of class into reflection.
Use Cases
- Deserialization and serialization json, as in (ts-serializable)
- DI library as AngularDI or (first-di)
Examples
import { Serializable } from "ts-serializable";
@extractInterface()
export class User extends Serializable {
public firstName: string = '';
public lastName: string | null = null;
public birthdate: Date = new Date();
public getFullName(): string {
return [
this.firstName,
this.lastName
].join(' ');
}
public getAge(): number {
return new Date().getFullYear() - this.birthdate.getFullYear();
}
}
const user: User = new User().fromJSON(json);
user.getFullName(); // return fullname
user.getAge(); // return age
// or
const user: User = User.fromJSON(json);
user.getFullName();
user.getAge();
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.