【问题标题】:Cannot invoke an expression whose type lacks a call signature. Type 'UserModel' has no compatible call signatures无法调用其类型缺少调用签名的表达式。类型“UserModel”没有兼容的调用签名
【发布时间】:2019-04-14 10:09:05
【问题描述】:

当我尝试在 user.service.ts 中设置属性时遇到类型错误。 这就是 user.service 的样子:

import { Injectable } from '@angular/core';
import { UserModel } from '../models/user.model';

@Injectable()
export class UserService {
  private _user: UserModel;
  constructor() {}

  get getUser(): UserModel {
    return this._user;
  }
  set setUser(user: UserModel) {
    this._user = user;
  }
}

和用户模型:

export class UserModel {
  constructor(public uid: string,
              public displayName: string,
              public email: string,
              public photoUrl: string,
              public providerId: string) {}
}

最后这是我得到错误的 auth.service。

import {Injectable} from '@angular/core';
import * as firebase from 'firebase';
import { AngularFireAuth } from 'angularfire2/auth';
import {Router} from '@angular/router';
import { UserModel } from '../models/user.model';
import { UserService } from './user.service';


@Injectable()
export class AuthService {
  private _token: string = null;

  // We use first login in app.module to check if is the first login. If it is we skip the refresh token method.
  private _firstLogin = false;
  constructor(private afAuth: AngularFireAuth,
              private router: Router,
              private userService: UserService) {}

  get isFirstLogin() {
    return this._firstLogin;
  }
  get getUserToken(): string{
    return this._token;
  }
  set setUserToken(tk: string) {
    this._token = tk;
  }
  // We define the Facebook provider and passing it to signin(). We do this for each provider that we want to integrate.
  signinWithFacebook(): Promise<any> {
    const fbProvider = new firebase.auth.FacebookAuthProvider();
    return this.signin(this.afAuth.auth.signInWithPopup(fbProvider));
  }

  // If this method get resolved then we redirect the user to the home page and get the token.
  // Besides, when this method execute the reject() we catch it in the login component and we handle the errors there.
  // This method can be reusable across multiple providers such Facebook, Twitter, Github , etc.
  signin(popupResult: Promise<any>): Promise<any> {
    return popupResult
      .then(
        (res) => {
          this._firstLogin = true;
          const user: firebase.User = res.user.toJSON();
          const credential = res.credential;
          this._token = credential.accessToken;

          // Initialising the user and passing to the user service's property (_user)
          // TODO fix: Solucionar error de la línea 51.
          const providedData = user.providerData[0];
          const buildedUser = new UserModel(providedData.uid, providedData.displayName,
            providedData.email, providedData.photoURL, providedData.providerId);
          this.userService.setUser(buildedUser); //HERE I GOT THE ERROR.

          console.log(this._token);
          console.log(user);
        }
      );
  }
}

当我尝试在以下代码行中将 UserModel 从 auth.service 传递给 user.service 时出现错误:this.userService.setUser(buildedUser)。 我希望你能得到它并给我一个解决方案,并告诉我为什么会发生这种情况。 问候!

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    UserService 中的方法中删除getset

    @Injectable()
    export class UserService {
      private _user: UserModel;
      constructor() {}
    
      getUser(): UserModel {
        return this._user;
      }
      setUser(user: UserModel) {
        this._user = user;
      }
    }
    

    您可能不想将setter 用于setUser()。如果您执行 this.userService.setUser = buildedUser 之类的操作,将会调用 setter。如果你想像this.userService.setUser(buildedUser) 这样称呼它,那么setUser() 只是一个普通的旧方法。

    同样,当您获取用户时,您可能想要调用const retrievedUser = this.userService.getUser(),而不是const retrievedUser = this.userService.getUser。前者只是一个简单的方法,而后者将是一个吸气剂。


    如果你真的想使用 getter 和 setter,你可以保留 getset 但也可以将 getUsersetUser 重命名为 user

    @Injectable()
    export class UserService {
      private _user: UserModel;
      constructor() {}
    
      get user(): UserModel {
        return this._user;
      }
      set user(user: UserModel) {
        this._user = user;
      }
    }
    

    然后调用this.userService.user = buildedUserconst retrievedUser = this.userService.user,你的setter 和getter 就会被调用。

    但是 getter 和 setter 背后的想法是,调用者将它们视为只是属性访问,而您可以将它们实现为不仅仅是获取和设置属性的方法。如果您所做的只是获取和设置属性,那么您不妨拥有一个名为 user 的公共属性:

    @Injectable()
    export class UserService {
      public user: UserModel;
      constructor() {}
    }
    

    这仍然可以让您更轻松地完成this.userService.user = buildedUserconst retrievedUser = this.userService.user


    【讨论】:

    • 谢谢。我打算将它与 setter 一起使用,但很高兴你已经澄清了它。
    • 由于多态性,我已将用户设置为私有。 UserService 快创建好了,以后会有更多的逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    • 2017-10-11
    • 2020-05-17
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多