Striker1440
Striker1440

Reputation: 55

Is there a way to get the declared type of a property rather than the type of the assigned value in typescript

I am attempting to create a generic model class in typescript that can be extended by child models for the purposes of creating an automatic HTTP data to model processing method in the super class.

A basic child model might be as such:

export class User extends Model {

    private username: string = null;

    constructor () {
        super ();
        this.processJson ();
    }
}

With our parent Model class doing something like:

export class Model {

    constructor () {
    }

    public processJson<T> () {

        _.forEach (Object.keys (this), (key: string) => {
            console.log (`processing key: ${key}`);
            console.log (typeof this[key]);
        })
   }
}

The plan is to use the processJson method a single entry point to take inbound JSON data and process it into our child models according to their definition.

The issue here is that I can't seem to get the declared type that is defined in the child model, in the provided example the typeof this[key] will return object since it infers the type of the assigned value in this example null.

My plan is to use this for more complex cases where we might have more complex objects or different types that have special processing and perform it all in a centralized place within our parent Model class.

My question is as such, how can I knowing the properties of the child model, get the declared type of our example of username as string NOT object ?

Is this a limitation of the underlying JavaScript that is generated? or am I misunderstanding how declared class properties work in Typescript?

I know that when declaring a property as:

private username: string = '';

It will give me the correct type, but I don't want to initialize values until they are assigned by the JSON data as in some cases null might be a valid value.

Upvotes: 2

Views: 752

Answers (3)

rkparmar
rkparmar

Reputation: 142

Sample code:

class Circle {
    public kind: string = '';
    public radius: number = 0;
}

let objCircle: Circle;

objCircle = { 
    kind: 'circle1', 
    radius: 123 
} as Circle;

console.log(typeof objCircle.kind === 'string')  // true
console.log(typeof objCircle.radius === 'number') // true
console.log(objCircle instanceof Object) // true

Upvotes: 0

rkparmar
rkparmar

Reputation: 142

You can check declared type using typeof, === strict comparison and instanceof

enter image description here

Upvotes: 0

amakhrov
amakhrov

Reputation: 3939

Your code snippet assumes you need the typescript's type information at run time. However, at run time all types are erased by typescript compiler. It only emits plain javascript without type annotations.

I believe your best bet would be to create a decorator and decorate every property of a model with it - like this:

class User extends Model {
  @ModelField private username: string;
}

Also make sure you enable emitDecoratorMetadata compiler option (https://www.typescriptlang.org/docs/handbook/decorators.html#metadata)

It should allow you to read the type of a decorated property via reflect-metadata (e.g as suggested in this answer: How to get type data in TypeScript decorator?).

Upvotes: 3

Related Questions