Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript default properties when type casting

Tags:

typescript

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?

like image 786
Guerrilla Avatar asked Mar 13 '17 22:03

Guerrilla


2 Answers

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};
like image 91
Meirion Hughes Avatar answered Nov 14 '22 01:11

Meirion Hughes


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.

like image 34
Eliran Malka Avatar answered Nov 14 '22 00:11

Eliran Malka