Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript computed getter not working

This computed property lastSeenString used to be working for me:

export class User {
    public lastSeen?: Date;
    private _lastSeenString?:string = "";
    get lastSeenString():string {
        return Time.timeSince(this.lastSeen);
    }
}

But now lastSeenString returns "". The return statement in the getter is never called. How come? lastSeen is populated.

client:

it('Displays the user\'s "last seen"', () => {
    component.user.lastSeen = new Date();
    fixture.detectChanges();
    expect(component.user.lastSeenString).toBe("less than a minute ago");
    expect(page.lastSeen.innerText).toBe("last seen less than a minute ago");
});

My typescript compiles to es5. Why does code inside the getter not execute?

Time class which is supposed to get executed but doesn't:

export class Time {
    public static timeSince(date: Date) {
        let start = +new Date();
        let elapsed = +new Date() - start;
        var seconds = Math.floor((elapsed) / 1000);

        // var seconds = Math.floor((new Date() - +date) / 1000);

        //var seconds = Math.floor(((new Date().getTime()/1000) - +date))


        var interval = Math.floor(seconds / 31536000);

        if (interval > 1) {
            return interval + " years";
        }
        interval = Math.floor(seconds / 2592000);
        if (interval > 1) {
            return interval + " months";
        }
        interval = Math.floor(seconds / 86400);
        if (interval > 1) {
            return interval + " days";
        }
        interval = Math.floor(seconds / 3600);
        if (interval > 1) {
            return interval + " hours";
        }
        interval = Math.floor(seconds / 60);
        if (interval > 1) {
            return interval + " minutes";
        }
        return "less than a minute ago";
    }
}

actual implementation of the User class:

export var SERENA: User = {
   id: 1,
   lastSeenString: "",
    lastSeen: new Date("October 13, 2016 11:13:00"),
    badges: ["active User", "helper"],
    memberSince: new Date("October 13, 2014")
}

I see the implementation has lastSeenString = "", however I thought that would trigger the getter rather than just return "".

Update: I'm pretty sure it must be to do with just exporting that JSON object and calling it a User. I think I must have to new it up.

like image 432
BeniaminoBaggins Avatar asked Dec 08 '16 05:12

BeniaminoBaggins


2 Answers

The getter is defined on the prototype of User - i.e. as part of the class itself. You need to build your instance using that class (e.g. with new User()) for the getter to work.

Currently you just build a vanilla JavaScript object, and then tell TypeScript that it's the same shape as a real User object. That passes type checking, because it is the same shape - reading any field on it will return values of the same type that you'd be expecting from a real User object - but that doesn't tell you anything about the underlying behaviour of those fields.

like image 77
Tim Perry Avatar answered Nov 14 '22 00:11

Tim Perry


In my case, I was getting object data from the network as JSON. Then assigned the data like this:

   let newUser = Object.assign(new User(), data)

I could access all of the public data and functions, but couldn’t access functions, getters, setters for objects inside this object. So I had no access to private data even though I could print them out.

   class User {
      name: string
      state: UserState
    }

   class UserState {
      private _stateInfo: string
      getter()......
    }

So I can access name, and can print out the data of state. But can’t access functions inside state.

The way to solve this is to initialize new UserState object when passing the data for User object.

like image 37
demiculus Avatar answered Nov 14 '22 00:11

demiculus