6

Is there a way to typecast an object to a class type so that default property values are respected?

For instance:

class Person {
    name: string = "bob";
    age: number;
    sex: string;
}

var data = {
    "age": 23,
    "sex": "male"
}

var p = <Person>data;

console.log(p.name); // -> undefined

What is the simplest way to do it so p.name is bob?

*Edit

This seems to work:

var record : Person = Object.assign(new Person(), p);

Is this good or bad practice?

2
  • you should clarify your question. Do you want an instance of class or enforce the type when casting an object? for example var p:Person = {name="default", ... data} will work and enforce the type, but it isn't an instance of the class. For that you'd probably be better off with a class constructor that takes an initializer. see: stackoverflow.com/questions/14142071/… Commented Mar 13, 2017 at 23:17
  • I want instance of class populated with data from the json. Commented Mar 13, 2017 at 23:20

2 Answers 2

5

The simplest way that gives you an instance of the class is to use a constructor initialiser and make the fields with defaults optional:

class Person {
  name?: string = "bob";
  age: number;
  sex: string;
  constructor(opt: Person) {
    Object.assign(this, opt);
  }
} 

or be explicit in what is and is not optional for initialization.

class Person {
  name: string = "bob";
  age: number;
  sex: string;
  constructor(opt: { name?: string, age: number; sex: string; }) {
    Object.assign(this, opt);
  }
}

or, if you don't care what is given just make the initializer fields all optional:

class Person {
  name: string = "bob";
  age: number;
  sex: string;
  constructor(opt?: Partial<Person>) {
    Object.assign(this, opt);
  }
}

if you don't care about it being an instance of the class, but you want to enforce the fields and types then avoid casting and set the type of the variable explicitly instead:

var data = {
    "age": 23,
    "sex": "male"
}

var p1:Person = {name:"bob", ... data}; // or
var p2:Person = {new Person(), ... data};
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Why must default fields be optional?
it means you don't have to pass them through in the initialiser: eg: new Person({age:20, sex:"male"})
1

There is no way to do so with Type Assertions (type casting); they're evaluated at compile time, whereas Default Values are resolved at runtime.

They are completely disparate phases.

4 Comments

What would be the way to go about doing it? Any way to instantiate the object then merge properties after so default values are there?
yes, you can spread them along with your instance: {...p, ...overrides}. or, if you want defaults: {...defaults, ...p}. you're gonna have to use new at some point either way.
I read that page on spread. I couldn't see any apparent way it could be applied to merge objects. I got it working with Object.assign(new Person(), p) though, not sure if thats a good practice to initiate all objects with default properties like that.
@Guerrilla - sounds awesome. if it suits your needs, you should post it as an answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.