Typescript: Add function to Date prototype and keep other methods

Created on 29 Mar 2016  路  11Comments  路  Source: microsoft/TypeScript

Hello,

I want to add a function to the Date prototype. I want to add a weekNumber function to it that returns the number of the week.

I wan to create make it on the typescript way so much as posible.

This is the prototype function:

Date.prototype.getWeekNumber()
    var d: Date = new Date(+this);
    d.setHours(0, 0, 0);
    d.setDate(d.getDate() + 4 - (d.getDay() || 7));
    return Math.ceil((((d - new Date(d.getFullYear(), 0, 1)) / 8.64e7) + 1) / 7);
};

I created a interface but the problem was that he removed all the functions of the Date and becease of that my IDE was giving an error that the functions are not existing.

Does someknow how to do it by the right way?`

Question

Most helpful comment

Lambda expressions do not have a this binding. they inherit the one from the containing scope. in this case, it is the module. This is the ES2015 semantics of lambdas.

use a function expression instead. e.g.:

Date.prototype.isToday = function (): boolean {
 ... 
};

All 11 comments


// Extend the type, and declare the new function
interface Date {
    getWeekNumber(): number;
}

// Add the implementation
Date.prototype.getWeekNumber = function () {
....
};

var x = new Date();


x.getWeekNumber();

The problem with this is that all the methods of the Date are not available anymore

See https://github.com/Microsoft/TypeScript/wiki/FAQ#why-did-adding-an-import-or-export-modifier-break-my-program . The interface Date { declaration needs to not be an a module file.

What is the right way to do it? @RyanCavanaugh

Take the interface Date { declaration and put it in a .d.ts file that doesn't have any top-level import or export statements in it, then reference that .d.ts file in your compilation (either through a /// <reference or by adding it to the list of files on the commandline or tsconfig.json)

if you are using TS 1.8.5 or higher, consider using:

declare global {
    interface Date {
        myMethod(): number;
    }
}

see https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#augmenting-globalmodule-scope-from-modules for more details.

How to access the "date object" ?
Or whatever object i am extending..

Using this will return the first exported object in that file?!

... some angular2 stuff here ...


// DATE EXTENSIONS
// ================

declare global {
  interface Date {
    isToday(): boolean;
  }
}

Date.prototype.isToday = (): boolean => {
  let today = new Date();
  console.log(this); // WILL RETURN FIRST EXPORTED ANGULAR2 OBJECT IN THIS FILE
  return today.getFullYear() === this.getFullYear() && today.getMonth() === this.getMonth() && today.getDate() === this.getDate();
};

same behavior on top of the file.

EDIT:

tried in a separate file:

date.extensions.ts

export {}

// DATE EXTENSIONS
// ================

declare global {
   interface Date {
      addDays(days: number, useThis?: boolean): Date;
      isToday(): boolean;
      clone(): Date;
      isAnotherMonth(date: Date): boolean;
      isWeekend(): boolean;
      isSameDate(date: Date): boolean;
   }
}

Date.prototype.addDays = (days: number): Date => {
   if (!days) return this;
   console.log(this);
   let date = this;
   date.setDate(date.getDate() + days);

   return date;
};

Date.prototype.isToday = (): boolean => {
   let today = new Date();
   return this.isSameDate(today);
};

Date.prototype.clone = (): Date => {
   return new Date(+this);
};

Date.prototype.isAnotherMonth = (date: Date): boolean => {
   return date && this.getMonth() !== date.getMonth();
};

Date.prototype.isWeekend = (): boolean => {
   return this.getDay() === 0 || this.getDay() === 6;
};

Date.prototype.isSameDate = (date: Date): boolean => {
   return date && this.getFullYear() === date.getFullYear() && this.getMonth() === date.getMonth() && this.getDate() === date.getDate();
};

// EOF

date-picker.component.ts

.. imports ..

import './date.extensions';

.. angular2 stuff ..
.. trying to use the extended methods in here ! ..

see the following error message in console:

Uncaught TypeError: date.getDate is not a functionDate.addDays @ date.extensions.ts:21(anonymous function) @ month-view.component.ts:39ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.ts:61ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256ZoneTask.invoke @ zone.js:423

and logging this inside the addDays function prints out the window-object ..

Lambda expressions do not have a this binding. they inherit the one from the containing scope. in this case, it is the module. This is the ES2015 semantics of lambdas.

use a function expression instead. e.g.:

Date.prototype.isToday = function (): boolean {
 ... 
};

@mhegazy Thanks alot!!

Took me many hours to play around but no success..
Thanks, works like a charm!

I figured the lambda issue already. Still didn't work. But thank you gfrSE. Adding export {} on top resolved my issue.

@mhegazy do you have documentation on that... it is great informaiton and would like to read more up on it.

Lambda expressions do not have a this binding. they inherit the one from the containing scope. in this case, it is the module. This is the ES2015 semantics of lambdas.
use a function expression instead. e.g.:
Date.prototype.isToday = function (): boolean {
...
};

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Zlatkovsky picture Zlatkovsky  路  3Comments

siddjain picture siddjain  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments

zhuravlikjb picture zhuravlikjb  路  3Comments

MartynasZilinskas picture MartynasZilinskas  路  3Comments