moment()。add()仅适用于文字值

时间:2017-01-20 17:04:08

标签: angular typescript momentjs

我在TypeScript中使用Moment.js(如果重要的话,在Angular 2下)。当我使用带有文字值的add()方法作为参数时,它可以正常工作:

moment().add(1, 'month');

但是,如果我尝试用字符串替换单位,则会失败:

let units:string = 'month';
moment().add(1, units);

出现此错误:

Argument of type '1' is not assignable to parameter of type 'DurationConstructor'.

我在这里做错了什么?

8 个答案:

答案 0 :(得分:19)

不推荐的反向过载add(unit: unitOfTime.DurationConstructor, amount: number|string)会产生歧义。

您可以通过将units的类型定义为DurationConstructor而不是string来解决此问题:

let units: moment.unitOfTime.DurationConstructor = 'month';
moment().add(1, units);

另一种选择就是使用const代替let,因此将推断文字类型:

const units = 'month';
moment().add(1, units);

答案 1 :(得分:2)

我的问题是我使用mins。 DurationConstructor的类型def是

namespace unitOfTime {
type Base = (
  "year" | "years" | "y" |
  "month" | "months" | "M" |
  "week" | "weeks" | "w" |
  "day" | "days" | "d" |
  "hour" | "hours" | "h" |
  "minute" | "minutes" | "m" |
  "second" | "seconds" | "s" |
  "millisecond" | "milliseconds" | "ms"
);

所以这个开箱即用:

refTime.clone().subtract(15, 'minute')

-k

答案 2 :(得分:2)

接受的答案的另一个选项是在参数中进行类型转换。确实没有什么区别,只是认为我会将这个答案作为一个选择。如果您想更简洁一点,也可以将unitOfTime从模块中导入。

import { unitOfTime } from 'moment';
import * as moment from 'moment';

option = {val: 30, unit: 'm'}
moment().add( this.querySince.val, <unitOfTime.DurationConstructor>this.querySince.unit )

答案 3 :(得分:2)

add的两个声明

  1. add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
  2. 已弃用 add(unit: unitOfTime.DurationConstructor, amount: number|string)

当打字稿需要匹配重载时,它会尝试采用最接近的打字稿。当您尝试传递units:string时,最接近的匹配项number|string第二次重载,因为任何字符串都将与此声明匹配,例如'qwe''rty'类型的string,但不是DurationArg2类型的moment.add(1,'months),它应作为第一个声明中的第二个参数。

调用1时,它将使用第一个声明,因为可以将import * as moment from 'moment' calculateRangeFromEnd(end: Date, unitsAmount: moment.DurationInputArg1, unitsMeasureMoment: moment.DurationInputArg2): IDateRange { return { endDate: end, startDate: moment(end).subtract(unitsAmount, unitsMeasureMoment).toDate() } } 强制转换为第一个签名中的第一个参数的类型,但不能在第二个签名中

因此,要解决此问题和类似问题,您应该说出确切要使用的内容。

示例1.将使用第一个签名

import * as moment from 'moment'

calculateRangeFromEnd(end: Date, unitsAmount: number | string, unitsMeasureMoment: moment.unitOfTimes.DurationConstructor): IDateRange {
    return {
      endDate: end,
      startDate: moment(end).subtract(unitsMeasureMoment, unitsAmount).toDate()
    }
  }

示例2。将使用第二个签名

decrease , increase

答案 4 :(得分:1)

不幸的是,以上答案均与我无关! 但是,这仅使魅力! :D

const startTime = moment().subtract(this.time.amount as moment.DurationInputArg1, this.time.unit as moment.DurationInputArg2);

答案 5 :(得分:0)

此问题是由于在库中添加,减去等函数的反向语法已被弃用引起的。以下是摘录:

moment.d.ts

add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
/**
 * @deprecated reverse syntax
 */
add(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;

在我的情况下,我希望单位和值都是变量,所以我必须编写一个函数将general字符串转换为可接受的字符串(&#34;小时&#34;,&#34;分钟& #34;等等。)

function convertToDuration (unit: string): Moment.unitOfTime.DurationConstructor {

if(unit ==  'seconds' || unit ==  'minutes' || unit ==  'hours' || unit ==  'days' || unit ==  'weeks' || unit ==  'months'){
    return unit;
}
else // Default unit is hours
    return 'hours';
}

现在调用此函数:

const time = moment().add(expiryTime.value, convertToDuration(expiryTime.unit));

TypeScript中expiryTime的定义:

interface ExpiryTimeDef {
value: number,
unit: string
}

答案 6 :(得分:0)

将类型定义从let更改为const

const units = 'month';
moment().add(1, units);

这对我有用。

答案 7 :(得分:0)

此答案基于所有先前将onItemSelected指定为问题原因的答案。

我将DurationInputArg2字段强制转换为Attribute,因为所有这些方法都将其作为最终超类,因此对于deprecated reverse syntax of add, subtract, etc functions in moment来说,我只需要记住unitOfTime.Base

add, subtract, startOf, endOf

对于大多数人来说,令人困惑的部分是as Base被标记为错误。当一个单元合格时修正。