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'.
ここで何が悪いのですか?
非推奨の逆オーバーロードadd(unit: unitOfTime.DurationConstructor, amount: number|string)
はあいまいさを生じます。
これを修正するには、units
のタイプをDurationConstructor
ではなくstring
として定義します。
let units: moment.unitOfTime.DurationConstructor = 'month';
moment().add(1, units);
もう1つのオプションは、const
の代わりにlet
を使用することです。そのため、リテラルタイプが推論されます。
const units = 'month';
moment().add(1, units);
受け入れられた回答の別のオプションは、引数の型キャストです。実際には違いはありません。この回答をオプションとして含めると考えただけです。さらに簡潔にするために、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 )
add
の宣言は2つあります
add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
add(unit: unitOfTime.DurationConstructor, amount: number|string)
TypeScriptがオーバーロードに一致する必要がある場合、最も近い型を取得しようとします。 _units:string
_を渡そうとしたときに、最も近い一致_number|string
_は2番目のオーバーロードです。これは、-任意の文字列がこの宣言に一致するためです。 _'qwe'
_、またはstring
タイプの_'rty'
_、ただし_DurationArg2
_ではない最初の宣言の2番目のパラメーターとして期待されています。
moment.add(1,'months)
を呼び出すと、最初の宣言が使用されます。これは、_1
_を最初のシグネチャの最初の引数の型にキャストできますが、2番目の型にはキャストできないためです。
したがって、この問題を修正するには、正確に何を使用したいかを言う必要があります。
例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()
}
}
_
例2. 2番目の署名が使用されます
_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()
}
}
_
私の場合の問題は、mins
を使用していたことです。 DurationConstructorの型定義は
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
この回答は、問題の原因としてdeprecated reverse syntax of add, subtract, etc functions in moment
を指定する以前のすべての回答に基づいています。
これらのメソッドはすべてこれを究極のスーパークラスとして持っているので、DurationInputArg2フィールドをunitOfTime.Base
にキャストします。つまり、add, subtract, startOf, endOf
を意味するので、as Base
を覚えておくだけです。
import Base = moment.unitOfTime.Base
theMoment.subtract(amount, unitString as Base)
theMoment.startOf(unitString as Base)
ほとんどの人にとって混乱する部分は、amount
がエラーとしてマークされていることです。ユニットを修飾するときに修正されました。
この問題は、モーメントライブラリ内の追加、減算などの関数の非推奨の逆構文が原因で発生します。以下は抜粋です。
moment.d.ts
add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
/**
* @deprecated reverse syntax
*/
add(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;
私の場合、単位と値の両方を変数にしたいので、general
文字列を許容可能な文字列(「時間」、「分」など)に変換する関数を作成する必要がありました。
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
}
タイプ定義をlet
からconst
に変更します
const units = 'month';
moment().add(1, units);
これは私のために働く。