Reputation: 55
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
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
Reputation: 142
You can check declared type using typeof
, ===
strict comparison and instanceof
Upvotes: 0
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