1

I'm using angular 7 (I guess it's the same for ver. 2.x) and I'm using something similar to httpClient.get<Hero[]>(url) with no other processing. Hero has also the dateOfBirth property which has the type Date; when obtaining the Hero array I see that the typeof dateOfBirth is string instead of Date.

Is that normal or not? how could one solve it (I mean getting somehow Date)?

PS1: I'm not looking for some manual conversion by using e.g. the RxJs map operator because I might have a tree of objects with many properties facing the same problem so using map would mean too much work

PS2: for the moment I'm solving the problem doing somewhere (a RxJs tap on that httpClient.get) in the code this:

if (typeof hero.dateOfBirth === 'string') {
  hero.dateOfBirth = new Date(hero.dateOfBirth);
}

The received JSON is e.g.:

"dateOfBirth" : "2018-12-17T20:04:32.721+0000"
Adrian
  • 3,321
  • 2
  • 29
  • 46
  • "when obtaining the Hero array I see that the typeof dateOfBirth is string instead of Date" --> how do you "see" ? are you looking at the console? – Roddy of the Frozen Peas Dec 17 '18 at 19:12
  • I check `typeof hero.dateOfBirth`. Also the `hero.dateOfBirth` doesn't have the `getTime()` method while other `Date` variables have it. – Adrian Dec 17 '18 at 19:14
  • if you could post more code, for example your Hero Model, your service (where you use httpClient) and where do you check your type – victor dencowski Dec 17 '18 at 20:00
  • I can't now but really, it's nothing special; I could e.g. check the property type in a RxJs `tap` - I do it as in PS2 above. – Adrian Dec 17 '18 at 20:10
  • 1
    can you share the returned json from back-end? – Reza Dec 17 '18 at 20:26
  • I'm sorry, I can't entirely but that's for the property: `"dateOfBirth" : "2018-12-17T20:04:32.721+0000"`. – Adrian Dec 17 '18 at 21:43
  • 1
    JSON doesn't have a specific `Date` type, only strings, ints, and booleans. This goes beyond Angular and into basic JS and AJAX calls. You need to manually convert any fields you want as a `Date` to `Date`s. – joh04667 Dec 17 '18 at 21:55
  • @adrhc There is no magic cast type library, you need yo do it manually for every property you want to convert from string to type you need. – Maksim Romanenko Dec 18 '18 at 08:32
  • See this related answer: https://stackoverflow.com/a/49279951/5409719 – kirodge Oct 21 '19 at 08:28

1 Answers1

1

The JSON format doesn't know anything about dates. JSON (mostly) only specifies singular values as numbers, strings, boolean, or null.

If you're expecting a field that's the result of an XMLHttpRequest to be a Date, you'll need to manually convert it like always:

httpClient.get<Hero[]>(url).pipe(
    map(hero => hero.map(h => {
        h.dateOfBirth = new Date(h.dateOfBirth);
        return h;
    })))

PS1: I'm not looking for some manual conversion by using the RxJs map operator because I might have a tree of objects with many properties facing the same problem so using map would mean too much work

Why not? You're going to have to iterate eventually; sure, you can abstract this somewhere else or into an Observable operator, but it makes sense to format the data in the Observable stream before it's emitted so it's consistent everywhere else.

joh04667
  • 7,159
  • 27
  • 34
  • ... because I might have a tree of objects with many properties facing the same problem so using map would mean too much work – Adrian Dec 17 '18 at 22:08
  • But still, you'd have to iterate through the tree and convert the properties at *some* point, so there's really no difference with doing it in the `Observable` stream versus elsewhere. If fact, many people would agree that using the stream and operators is better design than unwrapping it and doing it elsewhere. You could even write a higher-level lettable operator with `let` that takes a transform function and transforms values in the stream in a configurable way. I only see doing it elsewhere as *more* work, not less. – joh04667 Dec 17 '18 at 22:21
  • I didn't intend to avoid the conversion in `Observable` but everywhere. I don't want to do it at all manually; I would agree to use a library if exists. – Adrian Dec 17 '18 at 22:25
  • 1
    Even if a library existed, you'd have to configure it to your dataset so you'd essentially be doing the same thing. Why not just keep the fields as strings then? The `date` pipe accepts a string input. You'd just have to do manual conversion when you need to manipulate `Date` properties. If you want to avoid conversion or 'doing work' altogether, I'm not sure StackOverflow is the right place to ask these kind of questions. – joh04667 Dec 17 '18 at 22:31
  • It's I suppose easier to configure/use a library instead of converting many scattered properties. Don't be mean, I'm really trying to get the best solution here. – Adrian Dec 17 '18 at 22:34
  • Sorry if I came off as mean! I'm just encouraging you to try your own solution before looking for a library and subjecting your project to dependency hell / npm bloat. Often times there's a simple, elegant solution that you can write yourself instead of getting out the sledgehammer to kill a cockroach. Since type tokens are not compiled and there's no way to be aware of what *should* be a `Date`, I don't see any automagic way to do this -- maybe you could look for keys with the *word* 'date' in them and convert that way, or define getters/setters in the `Hero` class that convert for you? – joh04667 Dec 17 '18 at 22:45
  • It might be obvious that there's no other better solution but for these kind of situations on rare occasions I was surprised by smart individuals coming with incredible solutions. Hopefully will be the case here too. – Adrian Dec 17 '18 at 23:10