0

I have a Date prototype extension that I use in Angular project, defined as:

if (!Date.prototype.hasOwnProperty('toLocalISOString')) {
  Date.prototype.toLocalISOString = function (): string | null {
    try {
      const date = new Date(this.valueOf());
      const a = [
        { f: date.getFullYear(), pad: 4 },
        { f: date.getMonth() + 1, pad: 2 },
        { f: date.getDate(), pad: 2 },
        { f: date.getHours(), pad: 2 },
        { f: date.getMinutes(), pad: 2 },
        { f: date.getSeconds(), pad: 2 },
        { f: date.getMilliseconds(), pad: 3 }
      ];
      const s = a.map(d => d.f.toString().padStart(d.pad, '0'));
      return `${s[0]}-${s[1]}-${s[2]}T${s[3]}:${s[4]}:${s[5]}.${s[6]}`;
      //return `${s[0]}-${s[1]}-${s[2]}T${s[3]}:${s[4]}:${s[5]}.${s[6]}Z`;      //if using Z as identifier the time is considered UTC
    }
    catch {
      return null;
    }
  }

The extension is declared in my global.d.ts file as:

export { }
declare global {    
  interface Date {
    toLocalISOString(): string | null;
  }
}

With a function call in a component as below:

getAllSelect(startDate?: Date, endDate?: Date) {
    let params = new HttpParams();
    if (startDate && endDate)
    {      
       const d1 = new Date(startDate).toLocalISOString() ?? '';
       const d2 = new Date(endDate).toLocalISOString() ?? '';
    }

    'do stuff
}

if I use the function WITHOUT the new Date() initializer, i.e.

const d1 = startDate.toLocalISOString() ?? '';
const d2 = endDate.toLocalISOString() ?? '';

I get an error message that toLocalISOString is not a function even though startDate & endDate are both of type Date? if I include the new Date() initializer it works as intended.

Would anyone be able to shed some more light on the intricate differences between the two methods and why the prototype extension doesn't get recognized from the Date | null instance?

mtholen
  • 1,631
  • 2
  • 15
  • 27
  • Did you declare the ts extension? Ref: https://stackoverflow.com/questions/39877156/how-to-extend-string-prototype-and-use-it-next-in-typescript/53392268 – stWrong Nov 27 '21 at 01:04
  • @stWrong yes indeed, otherwise the extension would not work at all, in this case it works in the first case (when using `new Date()`) but doesn't if not using `new Date()` -question updated- – mtholen Nov 27 '21 at 01:19
  • "*even though `startDate` & `endDate` are both of type Date?*" - well, that's what TypeScript believes. But apparently they're not. Please do some debugging as for what their actual values are, and show us how you are calling `getAllSelect` so that we have a [mcve]. – Bergi Nov 27 '21 at 01:33
  • What is the point of `toSafeISOString`, why don't you just call `.toISOString()`? [Don't extend native objects](https://stackoverflow.com/q/14034180/1048572). And if you do, remove that `if (!Date.prototype.hasOwnProperty('toSafeISOString')) {` statement. – Bergi Nov 27 '21 at 01:36
  • @Bergi apart from not being part of the question (I wasn't asking if it is a good implementation) the point here is to remove the 'Z' from the `toISOString` as calling an MVC backend with the `Z` included marks the `DateTime` object as being of type 'UTC' and sets the timezone accordingly. but when retrieved that timezone setting translates to a DateTime object with timezone hours difference. This causes issues when working only with 'local' times/dates. – mtholen Nov 27 '21 at 04:42
  • @Bergi the main argument for not extending native objects is that you may interfere with other code that uses the native class. This would, in this case, only be a problem if another section of code would also have declared a `toSafeISOString` ? It is precisely because of that that the `!Date.prototype.hasOwnProperty('toSafeISOString')` is included? It should prevent instantiating the function with my code if it may accidentally already exist? – mtholen Nov 27 '21 at 04:55
  • @mtholen Well, and if another section of code did create a method with that name (or even if it was provided natively - it doesn't even have to be used), then your code wouldn't work anymore! So if your code relies on that method, it should be more assertive when creating it. – Bergi Nov 27 '21 at 05:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239626/discussion-between-mtholen-and-bergi). – mtholen Nov 27 '21 at 05:18

0 Answers0