2017-06-03 1 views
0

J'essaie d'utiliser des valeurs par défaut pour la destruction de l'objet littéral, mais je ne reçois pas les valeurs par défaut, juste 'non défini'. Quelle est la bonne façon?caractèrescript destructuring objet littéral dans la construction de la classe, les propriétés par défaut ne fonctionne pas

import { Component } from '@angular/core'; 
export class Hero { 
    id: number; 
    name: string; 
// constructor({id = 3, name = 'defaulthero'} = {}) { 
    constructor({id , name }: {id?: number, name?: string } = { id:3, name: 'defaulthero'}) { 
    console.log(id, name); 
    this.id = id; 
    this.name = name; 
    } 
} 

@Component({ 
    selector: 'my-app', 
    template: `<h1>{{title}}</h1><h2>Hero {{hero3.id}} {{hero3.name}}</h2>`, 
}) 
export class AppComponent { 
    title = 'Tour of Heros'; 
    public hero3: Hero; 


    ngOnInit() { 

    //this.hero3 = new Hero () ; // work 
    //this.hero3 = new Hero ( {}) ; // does not work 
    this.hero3 = new Hero ({id: 0}) ; // does not work, default value 'defaulthero' not assign, just i get 'undefined' 
    } 
} 

Répondre

1

J'ai trouvé deux solutions alternatives inspirées dans:

1) Solution classe Hero: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#improved-checking-for-destructuring-object-literal

2) Solution classe Hero2: section "Propriétés en option" 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' 
    } 
} 
+0

votre réponse est beaucoup plus trompeuse d'autres à créer une interface supplémentaire juste pour créer une instance de classe existante. En gros, vous devez utiliser 'constructor (id: string = '3', name = 'Spiderman')' ou la façon dont j'ai fourni un seul code de ligne. – Pengyy

0

Lorsque vous n'attribuez pas de valeur par défaut pour object fields, tapuscrit traitera comme paramètre normal (type d'objet) comme ci-dessous:

constructor(obj: any = {id:3, name: 'defaulthero'}) 
  • lors de la création d'une nouvelle instance de hero par new Hero(), il n'y aura pas de paramètre pour constructor, donc le {id:3, name: 'defaulthero'} par défaut sera utilisé.

  • lors de la création d'une nouvelle instance de hero par , il y aura un paramètre qui est un objet sans champ et il sera utilisé comme paramètre de revenu et prendre la place de défaut {id:3, name: 'defaulthero'}. (Le même que new Hero ({id: 0}))


que vous avez une ligne de commentaire à votre bloc de code, vous pouvez attribuer une valeur par défaut pour les champs de paramètres d'objet avec les modifications ci-dessous:

constructor({id=3, name='defaulthero'}: {id?: number, name?: string } = {}) { 
    this.id = id; 
    this.name = name; 
} 

Plunker demo

+0

avertissement: toutes les variables doivent avoir, quand tapuscrit trouver une erreur avec tutoriel héros anguleux, vous voyez la dernière compilation ok, alors vous pensez que cela fonctionne, mais non, erreur avec tapuscrit n'est pas « ? » compiler vraiment; Mieux vaut rompre et lancer NPM Start, pour être sûr. – stackdave

+0

désolé, mais j'ai trouvé un meilleur deux solutions, regardez ma propre réponse – stackdave

0

Il fonctionne comme prévu, vous définissez une valeur par défaut pour l'objet puis il devient DESTRUCTED. Si vous remplacez cet objet par le vôtre, seules les valeurs qu'il contient remplissent vos arguments. Cependant, voici une façon d'archiver le comportement que vous voulez, au lieu de mettre en valeur par défaut de l'objet:

constructor({id, name }: {id?: number, name?: string } = {id:3, name: 'defaulthero'}) { 
    console.log(id, name); 
    this.id = id; 
    this.name = name; 
    } 

Est-ce pour chaque argument:

constructor({id = 3, name = 'defaulthero'}: {id?: number, name?: string } = {}) { 
    console.log(id, name); 
    this.id = id; 
    this.name = name; 
    }