I'm using Moment.js in TypeScript (under Angular 2 if that matters). When I use the add() method with literal values as arguments, it works fine:
moment().add(1, 'month');
However, if I try to replace the units with a string, it fails:
let units:string = 'month';
moment().add(1, units);
with this error:
Argument of type '1' is not assignable to parameter of type 'DurationConstructor'.
What am I doing wrong here?
There are two declarations of
add
add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
add(unit: unitOfTime.DurationConstructor, amount: number|string)
When typescript need to match overloads it tries to take closest type. When you've tried to pass
units:string
, closest matchnumber|string
is second overload, because any string will match to this declaration, f.e.'qwe'
, or'rty'
of typestring
, but notDurationArg2
which is expected as second parameter in first declaration.When you call
moment.add(1,'months)
it will use first declaration, because it is possible to cast1
to type of the first argument in first signature, but not in the second.So to fix this issue and similar, you should say what you exactly want to use.
Example 1. First signature will be used
Example 2. Second signature will be used
The problem in my case was that I was using
mins
. The type def for DurationConstructor isSo this works out of the box:
-k
Another option to the accepted answer is typecasting in the argument. There's really no difference, just figured I'd include this answer as an option. Also unitOfTime can be imported from moment as a module if you want some more brevity.
This problem is caused by deprecated reverse syntax of add, subtract, etc functions in moment library. Below is an excerpt:
moment.d.ts
In my case I wanted units and value both to be variables so I had to write a function to convert the
general
string to the acceptable ones ("hours", "minutes", etc.).Now to call this function:
Definition of expiryTime in TypeScript:
Deprecated reverse overload
add(unit: unitOfTime.DurationConstructor, amount: number|string)
creates ambiguity.You can fix this by defining type of
units
to beDurationConstructor
instead ofstring
: