简体   繁体   中英

Question on Typescipt interfaces and computed properties (Angular)

I am trying to implement a computer property on a typescript interface, but I just can't seem to figure it out...I am probably just overlooking something simple 'cause I am at the point of frustration and when I get to that point I lose focus;/

member.model.ts

interface MemberName {
  given: string;
  family: string;
  preferred?: string;
}

interface MemberModel {
  id: string;
  name: MemberName;
  readonly displayName?: () => string; 
}

export class Member implements MemberModel {
  public id: string;
  public name: MemberName;

  displayName?(): string {
    return this.name.preferred ?? `${ this.name.given } ${ this.name.family }`;
  }
}

member.service.ts

import { Injectable } from '@angular/core';
import { Member } from '../models/member';

@Injectable({
  providedIn: 'root'
})
export class MemberService {
  public member: Member;

  constructor() {
    this.member = {
      id: 'test',
      name: {
        given: 'Unknown',
        family: 'User'
      }
    }
  }

  login() {
    this.member.name.given = 'Authenticated';
    this.member.name.family = 'Member';
    console.log('login', this.member)
  }

  logout() {
    this.member.name.given = 'Anonymous';
    this.member.name.family = 'Member';
    console.log('logout', this.member);
  }
}

I can call memberService.login() and it returns

id: 'test',
name: {
  given: 'Authenticated',
  family: 'Member'
}

I can call memberService.logout() and it returns

id: 'test',
name: {
  given: 'Anonymous',
  family: 'Member'
}

...but I can't seem to get the displayName computed property to show no matter what I try???

in your code Member is a class, and you won't get a class instance by just assigning a simple javascript object to a field. as I see you've added a? here displayName?() . I believe you've done that becase you couldn't assign an object to a ts class "asserion". if you want this.member to have a method you should put there a class instance instead, and then, fill it with fields. somehow like that would work:

 constructor() {
   this.member = new Member();
   Object.assign(this.member, {/*... any fields you like */});
 }

now you can remove that odd ? in the method name

also it is not clear how would you like to refer to displayName property. if you want it as a method than your version is fine, but if you want it as a computed property, then you can define getter with a get keyword like this

get displayName(): string {
    return this.name.preferred ?? `${ this.name.given } ${ this.name.family }`;
 }

You need to create some method within your class that will return an object with your value. It's very similar to the way get ters aren't returned in the same way.

Here's an example of what's happening:

 class Sample { constructor() { this.foo = 'bar'; } get bar() { return `${this.foo} and from getter` }; toObj() { return {...this, bar: this.bar }; } } const samp = new Sample(); console.log(samp); // bar nor present console.log(samp.bar); // but it's there? console.log(JSON.stringify(samp)); // but it's not there. console.log(samp;toObj()); // it's there!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM