我在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'.
我在这里做错了什么?
答案 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
的两个声明
add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
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
被标记为错误。当一个单元合格时修正。