Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript - passing a class as an argument, and reflection

I am writing a generic unmarshaller. It converts graph DB data to generated TypeScript (1.8.7) model classes. The input is JSON. The output should be an instance of a model class.
My ultimate goal is to create something like Hibernate OGM, only for Tinkerpop Frames and TypeScript, with REST endpoint in the middle.

What's the right way to pass a class as a parameter and reach it's static members? I want to have something like this:

SomeModel some = <SomeModel> unmarshaller.fromJSON({/*Object from JSON*/}, SomeModel);

I've tried to write a method. Not sure if I am heading in the right direction, feel free to suggest different approaches.

public fromJSON(input: Object, clazz: typeof FrameModel): FrameModel
{
    // This only demonstrates access to Framemodel's metadata 
    // about original Java model classes.
    clazz.graphPropertyMapping;
    clazz.graphRelationMapping;

    let result = {};
    ...
    return result;
}
...

But when I tried to execute this on Plunker, I got execution errors with unuseful stacktrace.

The model superclass looks like this:

/**
 * Things common to all Frames models on the Typescript side.
 */
export class FrameModel
{
    // Model metadata
    static discriminator: string;
    static graphPropertyMapping: { [key:string]:string; };
    static graphRelationMapping: { [key:string]:string; };

    // Each instance needs a vertex ID
    private vertexId: number;
    public getVertexId(): number {
        return this.vertexId;
    }
}

Sample model class:

import {TestPlanetModel} from './TestPlanetModel';
import {TestShipModel} from './TestShipModel';

export class TestGeneratorModel extends FrameModel
{
    static discriminator: string = 'TestGenerator';
    static graphPropertyMapping: { [key:string]:string; } = {
        bar: 'boo',
        name: 'name',
        rank: 'rank',
    };
    static graphRelationMapping: { [key:string]:string; } = {
        colonizes: 'colonizedPlanet',
        commands: 'ship',
    };

    boo: string;
    name: string;
    rank: string;

    public colonizedPlanet: TestPlanetModel[]; // edge label 'colonizedPlanet'

    public ship: TestShipModel; // edge label 'ship'

}

I haven't found much material on reflection and class handling in TypeScript.
I know how I would do this in Java.
I know how I would do this in JavaScript.
I understand that I might achieve similar results with decorators, but having fields or static fields seemed a bit simpler, for generated models.

like image 471
Ondra Žižka Avatar asked Nov 08 '22 11:11

Ondra Žižka


1 Answers

You've maybe already noticed that class members cannot have const keyword. But you could go with static instead. Also member should be public if you want it to be accessible from outside world.

public static graphPropertyMapping: { [key:string]:string; } = {
    bar: 'boo',
    name: 'name',
    rank: 'rank',
};

As for creating result instance:

let result = new clazz();

//copy properties

return result;
like image 133
Aleksey L. Avatar answered Nov 15 '22 12:11

Aleksey L.