Angular 8 getRole 不是嵌套对象中的函数

Angular 8 getRole is not a function in nested object

我有一个 API,那个 returns 我 Profile 信息,我正在我的 HTTP 服务中获取它。嵌套对象 User 有一个方法 getRole()。但是当我试图调用这个方法时,我得到

ERROR TypeError: _co.profile.user.getRole is not a function

当我从其他服务获取 User 时,只有 returns User 实体,我可以毫无问题地调用此函数。

我错过了什么?

型号

export class Profile {
  user: User;
  apiKeys: ApiKey[];
}

export class User {
  user: string;
  firstname: string;
  surname: string;
  email: string;
  role: Role;
  active: boolean;

  getRole() {
    switch (this.role) {
      case Role.READ: {
        return "READ";
      }
      case Role.WRITE: {
        return "WRITE";
      }
      case Role.ADMIN: {
        return "ADMIN";
      }
      default : {
        return "READ";
      }
    }
  }
}

ProfileService.ts

getProfile(): Observable<Profile> {
    return this.http.get<Profile>(this.profileUrl).pipe(catchError(this.handleError));
}

Component.ts

profile: Profile;
isProfileAvailable:boolean = false;

ngOnInit() {
  this.settingsService.getProfile().subscribe(profile => {
    this.profile = profile;
    this.isProfileAvailable = true;
   });
}

Component.html

<p-fieldset [legend]="Profile" *ngIf="isProfileAvailable">
    <div><b>User: </b>{{profile.user.firstname}}</div>
    <div><b>E-mail: </b>{{profile.user.email}}</div>
    <div><b>Role: </b>{{profile.user.getRole()}}</div>
</p-fieldset>

您目前没有创建 class 的实例,因此 class 方法 getRole() 不可用。使用 this.http.get<Profile> 你只是告诉编译器你对 API 的期望符合你的 class,它实际上并没有创建你的 class 或 sub[= 的实例31=] User.

您需要使用属性向 classes 添加一个构造函数,并实际创建 class 的 实例 。这是一个简化的例子:

export class User {
  role: string;

  constructor(role: string) {
    this.role = role;
  }

  getRole() {
    switch (this.role) {
      case 'READ': {
        return "READ";
      }
      case 'WRITE': {
        return "WRITE";
      }
      default: {
        return "READ";
      }
    }
  }
}

然后需要创建您的 class 实例以访问 class 方法:

ngOnInit() {
  let user = new User('WRITE');
  console.log(user.getRole());
}

STACKBLITZ

此外,如果这是您 class 中唯一需要的方法,我建议您改为使用接口并编写一个独立函数来检查角色,而不是经历创建过程的麻烦class 的实例。这是一个非常自以为是的事情,所以如果你想使用 classes 和 class 特定的方法,你确实需要走上面的路线。我只是喜欢个人使用接口:)

调用http.get<Profile>不会自动初始化Profile类型的对象,因此属性user也不是User类型的对象,并且还没有得到方法getRole

您可以使用 Object.assign 来初始化对象及其属性。并且因为有两种 class 类型(ProfileUser),两者都可以从 Base-Class 扩展来处理两者的属性分配类型。

型号:

// Use a Base class to assign all properties with objects both of type Profile and User
class Base {
    constructor(properties?: any) {
        (Object as any).assign(this, properties);
    }
}

export class User extends Base {
    user: string;
    firstname: string;
    surname: string;
    email: string;
    role: Role;
    active: boolean;

    getRole() {
        switch (this.role) {
            case Role.READ: {
                return "READ";
            }
            case Role.WRITE: {
                return "WRITE";
            }
            case Role.ADMIN: {
                return "ADMIN";
            }
            default : {
                return "READ";
            }
        }
    }  
}

export class Profile extends Base {
    user: User;
    apiKeys: ApiKey[];

    // take advantage of Object.assign
    // to initialize an instance of type Profile 
    // along with it's property user
    constructor(properties?: any) {
        super(properties);
        this.user = new User(properties.user);
    }
}

ProfileService.ts

getProfile(): Observable <Profile> {
    return this.http.get<Profile>(this.profileUrl).pipe(catchError(this.handleError));
}

Component.ts

profile: Profile;
isProfileAvailable:boolean = false;

ngOnInit()
{
    this.settingsService.getProfile().subscribe(profileData => {
        // assuming that profileData looks like this:
        /*
        {
            user: {
                user: 'user',
                firstname: 'firstname',
                surname: 'surname',
                email: 'email',
                active: true
            }
        }
        */
        this.profile = new Profile(profileData);
        this.isProfileAvailable = true;
    });
}

Blauharley 答案很有魅力。

但是,由于我的所有模型都在单独的文件中,所以我不得不导出 Base class:

export class Base {
    constructor(properties?: any) {
        (Object as any).assign(this, properties);
    }
}

一切正常。