[SOLVED] Bigint, Angular and HttpContext

Issue

I’m currently coming from ASP.Net MVC, trying to build an Angular application for my controller endpoints. My model, however; contains a ulong. This was fine, I presumed, as the JSON sent through the controller had this value correctly set. However; once it arrived in Angular, the value had been corrupted, and was ~50 off from what it should have been.

Later, I found this was due to Javascript’s limitations on the size of a number. The weird thing was, all my models in Angular were set to bigints, not numbers.

It’s quite possible that the JSON deserializer in Angular is treating these ulongs as numbers, not bigints, which would cause this corruption through JavaScript’s safe/unsafe size constraints. However, bigint has been in the specification for a few years by now, and I was wondering if there was any way around this?

I’ve looked at last StackOverflow answers for this problem, but many of them are from before bigint was introduced as a datatype officially.

For context, this is what I’m using in Angular to get my user data:

  private currentUserSubject = new ReplaySubject<any>();
  currentUser$ = this.currentUserSubject.asObservable();
  private init = false;

  constructor(private http: HttpClient, private router: Router, private cookieService: CookieService, private toastr: ToastrService) { }

  loadUserConfig() {
    this.http.get(API_URL + '/users/@me').subscribe((data) => {
      this.currentUserSubject.next(data);
    }, (error) => {
      this.currentUserSubject.error(null);
      this.handleError(error);
    });
  }

  getUserProfile(reinit: boolean = false): Observable<AppUser> {
    if (reinit || ( !this.init && this.isLoggedIn())) {
      this.init = true;
      this.loadUserConfig();
    }
    return this.currentUser$;
  }

Where AppUser is a model that contains another model, which has the bigint value in question. IE:

export interface Guild {
  id: bigint;
}

export interface AppUser {
  adminGuilds: Guild[];
}

Raw sent data:

{"adminGuilds":[{"id":613441321751019550}]}

I realise that I could send them across as strings, but sending them as ulongs and storing them as bigints is a much more elegant solution, in my opinion, than having to create seperate viewmodels that are identical to their model counterpart but with strings instead of ulongs.

-Ferox

Solution

BigInt in JS/TS is created by appending n to the end of an integer literal. Though you are using bigint type to represent your large numbers they are still being treated as numbers and hence you see loss of data in numbers.

Consider this:

interface Guild {
  id: bigint;
}

 interface AppUser {
  adminGuilds: Guild[];
}

const a: AppUser = {"adminGuilds":[{"id":613441321751019550}]};

Above will not compile in TS as the number 613441321751019550 is not a bignint but a number (as there is no n at the end. You will get the below error:

Type ‘number’ is not assignable to type ‘bigint’.

const a: AppUser = {"adminGuilds":[{"id":613441321751019550n}]};

It will compile fine and if you log alert(a.adminGuilds[0].id) you will not get data loss.

What you will need to do is add n at the end of numbers in your API response to be properly represented as bigint in JS/TS.

Answered By – Ritesh Waghela

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *