0

I have a typescript class:


 export class User {

    id: number;
    userName: string;
    knownAs: string;
    age: number;
    gender: string;
    created: Date;
    lastActive: Date;
    photoUrl: string;
    city: string;
    country: string;
    surname: string;
    givenname: string;

    get fullName(): string {
        return `${this.givenname} ${this.surname}`;
    }

    sayHello() {
        console.log(`Hello, my name is ${this.surname} ${this.givenname}!`);
      }
}

I have a Service function:



    user: User;
    this.userService.getUser(this.loggedUser.nameid).subscribe((user: User) => {
        this.user = user;
        this.user.givenname = this.loggedUser.given_name;
        this.user.surname = this.loggedUser.family_name;
        console.log(this.user.fullName);
        this.user.sayHello();
      });

the result in the console: console.log(this.user.fullName) = undefined this.user.sayHello(); = ERROR TypeError: Object doesn't support property or method 'sayHello'

After when I get back the user data from the server, how I can reach property and function which I've defined in the user class?

4
  • I think the issue is probably in your service class, which we would need the code for. Also, what does the debugger show you’re getting back? Commented Jan 16, 2019 at 15:55
  • Is the user result on the subscribe function actually an instance of the User class? Commented Jan 16, 2019 at 15:59
  • As @theMayer said, I think we will need the getUser() code to understand the error. Commented Jan 16, 2019 at 16:00
  • You're not creating an instance of User here ? You could use map Commented Jan 16, 2019 at 16:16

2 Answers 2

1

Try creating a prototype object for User like this. User you are getting from the service may not be a prototype object and hence the functions on it are not available.

user: User;
this.userService.getUser(this.loggedUser.nameid).subscribe((user: User) => {
    this.user = Object.assign(new User, user) //-->notice the use of new here..
    this.user.givenname = this.loggedUser.given_name;
    this.user.surname = this.loggedUser.family_name;
    console.log(this.user.fullName);
    this.user.sayHello();
  });

Update: JavaScript classes are not exactly an object oriented model. As per MDN:

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.

Read more here

Also, as pointed out by @theMayer in comment, the service that returns user can also return the proper User object which has the prototype functions. So, its the displacement of code to create the object from the client to service. I like that approach, just because that means any other consumer of the service can use the object behaviors (functions), without having to duplicate (Object.assign)the object.

So, in the UserService.ts (or wherever that userService is defined), something like:

getUser(id: string):User {
  //existing logig
  return Object.assign(new User(), user)//--> there are other ways to create object too, this is just one way.
}
Sign up to request clarification or add additional context in comments.

6 Comments

But this completely defeats the purpose of having a class in the first place, at least so far as TypeScript is concerned.
@theMayer you are right in a way, if you read at MDN, JavaScript classes are not really classes, its just a syntax improvement over the old Prototype based inheritance. Added the link to answer, explore more. Thx
Yes, but the whole purpose of Typescript is "compile-time" checking. So if you do this, you're getting all of the drawbacks and none of the benefits.
The issue you have is not TypeScript related. This is JavaScript classes behavior. Where TypeScript comes to play is, say for example, you are assigning an object that is not User to the variable user, like this.user = Object.assign(new OtherObject, user) then TypeScript will help you at compile time.
@theMayer you are right, sorry I took you for OP and kept explaining the answer =), yes, the service might as well create the user prototype object and return. That's an other way to do it if the OP has control over that service. I'll add that to the answer to improve. thx.
|
0

You're not creating an instance of User.
Here is an example of how it could be implemented :

 export class User {

    id?: number;
    userName?: string;
    knownAs?: string;
    age?: number;
    gender?: string;
    created?: Date;
    lastActive?: Date;
    photoUrl?: string;
    city?: string;
    country?: string;
    surname?: string;
    givenname?: string;

    constructor(args: User = {}) {
      this.id = args.id;
      this.userName = args.userName;
      this.knownAs = args.knownAs;
      this.age = args.age;
      this.gender = args.gender;
      this.created = args.created;
      this.lastActive = args.lastActive;
      this.photoUrl = args.photoUrl;
      this.city = args.city;
      this.country = args.country;
      this.surname = args.surname;
      this.givenname = args.givenname;
    }

    get fullName(): string {
        return `${this.givenname} ${this.surname}`;
    }

    sayHello() {
        console.log(`Hello, my name is ${this.surname} ${this.givenname}!`);
      }
}

Use map to create your User instance :

user: User;
this.userService.getUser(this.loggedUser.nameid)
  .pipe(map((user: User) => new User(user)))
  .subscribe((user: User) => {
    this.user = user;
    this.user.givenname = this.loggedUser.given_name;
    this.user.surname = this.loggedUser.family_name;
    console.log(this.user.fullName);
    this.user.sayHello();
  });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.