I\'m trying to use default values for destructuring object literal, but I don\'t get the default values, just \'undefined\'. What is the right way?
import { Comp
When you don't assign default value for object fields
, typescript will treat it as a normal parameter(type of object) like below:
constructor(obj: any = {id:3, name: 'defaulthero'})
when creating a new instance of hero
by new Hero()
, there will be no parameter for constructor
, so the default {id:3, name: 'defaulthero'}
will be used.
when creating a new instance of hero
by new Hero({})
, there will be one parameter which is an object with no fields and it will be used as the income parameter and take the place of default {id:3, name: 'defaulthero'}
.(the same as new Hero ( {id: 0} )
)
as you have one commented line at your code block, you can assign default value for fields of object parameters with the below changes:
constructor({id=3, name='defaulthero'}: {id?: number, name?: string } = {}) {
this.id = id;
this.name = name;
}
Plunker demo
It works as intended, you are setting a default value for the object and then it gets destructed. If you replace that object with your own, only values from it will populate your arguments. However, here is a way to archive the behaviour you want, instead of setting default value to the object:
constructor({id, name }: {id?: number, name?: string } = {id:3, name: 'defaulthero'}) {
console.log( id, name);
this.id = id;
this.name = name;
}
Do it for each argument:
constructor({id = 3, name = 'defaulthero'}: {id?: number, name?: string } = {}) {
console.log( id, name);
this.id = id;
this.name = name;
}
I've found two alternatives solutions inspired in:
1) Solution class Hero: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#improved-checking-for-destructuring-object-literal
2) Solution class Hero2: section "Optional Properties" https://www.typescriptlang.org/docs/handbook/interfaces.html
import { Component, OnInit } from '@angular/core';
interface HeroInterface {
// you need add ? for each variable (Optional Properties)
id?: number;
name?: string;
}
// Class using solution 1
class Hero {
id: number;
name: string;
//without interface: constructor({id= 3, name= 'defaulthero'}: {id?: number, name?: string } = {}) {
constructor({id= 4, name= 'Spiderman'}: HeroInterface = {}) {
this.id = id;
this.name = name;
}
}
// Class solution 2 ,using short way of assign property on constructor()
class Hero2 {
constructor(public config: HeroInterface = {}) { // short way to assign config like this.config = config;
if (!config.id) this.config.id =10;
if (!config.name) this.config.name = 'SuperMan';
}
}
@Component ( {
selector: 'my-app',
template: `hero1: id: {{hero.id}} name: {{hero.name}}
<br/>hero2: id: {{hero2.config.id}} name: {{hero2.config.name}}
`
})
export class AppComponent implements OnInit {
hero: Hero ;
hero2: Hero2 ;
ngOnInit () {
// SOLUTION 1:
// this.hero = new Hero ();
this.hero = new Hero ( { id:9 });
// SOLUTION 2:
this.hero2 = new Hero2 ( ); // Works with default values
//this.hero2 = new Hero2 ( { id: 20} ); // Works with default name value
//this.hero2 = new Hero2 ( { id: 20, name: 'Asterix'}); // send all values, don't need use default values
//this.hero2 = new Hero2 ( { id:19 , name: 'Asterix', weight:90}); // Error, 'weight' does not exist in type 'HeroInterface'
}
}