#DefaultScheduler
DefaultScheduler は、すぐ使えるスケジューラインスタンスを返す非同期ファクトリです。モデル(既定は FSRS-7)を dateChrono と標準のスケジュールポリシーに組み合わせるため、設定するのはオプションだけです。内部ではカスタムの defineScheduler と同じ「定義とインスタンス」の仕組みを使っています——プリセットは部品を便利に組み立てたものです。
#オプション
FSRS-3~6 から FSRS-7 に更新する際は、weights を省略して FSRS-7 の既定の重みを使うか、FSRS-7 用に学習した重みを指定してください。履歴の再生はカード状態を再構築するもので、旧版の重みは変換しません。
FSRS-7 のカードは stability と difficulty に加え stabilityFast を持ちます。FSRS-3~6 の記憶状態は Reschedule で復習履歴を再生して再構築してください。パラメータ移行はカード状態を移行せず、更新済みの高速トレースを 0.8 * stability で推測できません。FSRS-7 では小数日を使います。enableShortTerm: false は明示的な学習ステップだけを無効にし、高速トレースは無効にしません。
コストに応じた保持率には、独自の定義で schedulerDesiredRetentionMiddleware を schedulerCostAdrMiddleware に置き換えます。Cost ADR は DefaultScheduler のオプションではありません。
scheduler.nextInterval(memoryState, desiredRetention, { card, grade, elapsedDays }) は計算済みの評価後状態から間隔を問い合わせます。handlers.nextInterval だけを実行し、カードや chrono を進めません。共通の間隔ポリシーはこのフックに置いてください。
| オプション | 既定値 | 用途 |
|---|---|---|
version | 'FSRS-7' | FSRS モデルを選びます。'FSRS-3'、'FSRS-4'、'FSRS-4.5'、'FSRS-5', 'FSRS-6'、'FSRS-7'。FSRS-7 は旧版 FSRS-3~6 の重みを移行できません。 |
weights | プリセットの重み | 任意の学習済み重み。省略すると選択したバージョンの既定値を使います。FSRS-7 には FSRS-7 用の重みがちょうど 34 個必要です。旧版の重みを渡すと、スケジューラの構築時に例外が発生します。 |
desiredRetention | 0.9 | 間隔計算の前に適用する目標保持率。 |
enableShortTerm | true | 学習・再学習ステップを有効にします。 |
learningSteps | ['1m', '10m'] | enableShortTerm 有効時に適用する学習ステップ。 |
relearningSteps | ['10m'] | enableShortTerm 有効時に適用する再学習ステップ。 |
graduatingInterval | 1 | Review のカードの最短間隔(日)。最終間隔がこれより短いと Learning/Relearning に留まります。ステップを設定している場合、ステップを終えたときと Review のカードの Hard、Good、Easy は少なくともこの間隔を使います。 |
allowModelOverride | FSRS-7: true; その他のバージョン: false | モデルの間隔が現在のステップより長いとき、モデルの間隔を使います。Again は graduatingInterval を超えず、Hard と Good は間隔が graduatingInterval に達すると早期卒業します。 |
enableFuzz | false | 有効にすると間隔を分散して変化を付けます。 |
maximumInterval | 36500 | 間隔の日数上限。 |
clearStatsOnForget | true | forget が reps と lapses を消去するかどうか。 |
DefaultScheduler は常に dateChrono を使い、ミドルウェアページに示す順序で標準ポリシーを組み合わせます。目標保持率、fuzzing、統計、scheduled days、学習ステップ、最大間隔、単調間隔の順です。version を選ぶのはモデルとそのパラメータだけを変え、このポリシー構成は変わりません。
import { function DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7">(options?: DefaultSchedulerOptions<Version>): Promise<DefaultScheduler<Version>>
type DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7"> = (Version extends "FSRS-7" ? Omit<SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<FSRS7DefaultSchedulerModel, Chrono<{
readonly time: SRSSchema<{
input: Date;
output: Date;
}>;
readonly config: SRSSchema<{
input: {
readonly fractionalDays?: boolean | undefined;
};
output: {
readonly fractionalDays: boolean;
};
}>;
readonly fields: {
readonly card: SRSSchema<{
input: {
dueAt: Date;
lastReviewAt?: (Date | null) | undefined;
};
output: {
dueAt: Date;
lastReviewAt: Date | null;
};
}>;
readonly revlog: SRSSchema<{
input: {
dueAt: Date;
lastReviewAt?: (Date | null) | undefined;
reviewTime: Date;
};
output: {
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
};
}>;
};
}>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>, "definition"> : Omit<...> & {
...;
}) & {
...;
}
DefaultScheduler , type Rating = 0 | 1 | 2 | 3 | 4
const Rating: Readonly<{
readonly Manual: 0;
readonly Again: 1;
readonly Hard: 2;
readonly Good: 3;
readonly Easy: 4;
}>
Rating } from 'ts-fsrs'
const now = new Date('2026-01-01T00:00:00.000Z')
const const scheduler: DefaultScheduler<"FSRS-7"> scheduler = await DefaultScheduler<"FSRS-7">(options?: DefaultSchedulerOptions<"FSRS-7"> | undefined): Promise<DefaultScheduler<"FSRS-7">> DefaultScheduler ({
DefaultSchedulerOptions<"FSRS-7">.version?: "FSRS-7" | undefinedFSRS model and parameter migration version; defaults to FSRS-7.
version : 'FSRS-7',
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.desiredRetention?: number | undefined desiredRetention : 0.9,
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableShortTerm?: boolean | undefinedEnable explicit learning steps. FSRS-7 always retains its intrinsic fast trace.
enableShortTerm : true,
DefaultSchedulerOptions<"FSRS-7">.learningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefinedDefaults to ['1m', '10m'].
learningSteps : ['1m', '10m'],
DefaultSchedulerOptions<"FSRS-7">.relearningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefinedDefaults to ['10m'].
relearningSteps : ['10m'],
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableFuzz?: boolean | undefined enableFuzz : false,
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.maximumInterval?: number | undefined maximumInterval : 36_500,
})
const const card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
}
card = const scheduler: DefaultScheduler<"FSRS-7"> scheduler .newCard: (options?: ({
readonly cardId?: string | number | undefined;
} & {
readonly now?: Date | undefined;
}) | undefined) => {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
}
newCard ({ cardId: 'quick-start', now })
const const result: {
card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
};
revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
};
}
result = const scheduler: DefaultScheduler<"FSRS-7"> scheduler .review: (input: {
readonly card: Readonly<Omit<Readonly<{
stabilityFast: number;
stability: number;
difficulty: number;
} & {
dueAt: Date;
lastReviewAt: Date | null;
} & {
readonly cardId: string | number;
readonly reps: number;
readonly lapses: number;
readonly scheduledDays: number;
readonly learningStep?: number | undefined;
} & SchedulerCoreFields$1<"review" | "new" | "learning">>, keyof SchedulerCoreFields$1<"review" | "new" | "learning">> & SchedulerCoreFields$1<"review" | "new" | "learning">>;
readonly grade: Grade;
readonly now?: Date | undefined;
}) => {
...;
}
review ({ card, grade: const Rating: Readonly<{
readonly Manual: 0;
readonly Again: 1;
readonly Hard: 2;
readonly Good: 3;
readonly Easy: 4;
}>
Rating .Good, now })
console.log(
JSON.stringify(
{
state: const result: {
card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
};
revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
};
}
result .card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
}
card .state,
dueAt: const result: {
card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
};
revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
};
}
result .card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
}
card .dueAt,
stability: const result: {
card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
};
revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
};
}
result .card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
}
card .stability,
stabilityFast: const result: {
card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
};
revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
};
}
result .card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
}
card .stabilityFast,
difficulty: const result: {
card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
};
revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
};
}
result .card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
}
card .difficulty,
rating: const result: {
card: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reps: number;
lapses: number;
scheduledDays: number;
learningStep: number;
state: State;
scheduleStatus: "review" | "new" | "learning";
};
revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
};
}
result .revlog: {
cardId: string | number;
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
scheduledDays: number;
learningStep: number;
reviewTime: Date;
state: State;
scheduleStatus: "review" | "new" | "learning";
rating: Grade;
}
revlog .rating,
},
null,
2
)
)
このファクトリは非同期なので、返されたインスタンスを使う前に await DefaultScheduler(...) します。この例はよく使う既定値を明示しています。version、desiredRetention、学習・再学習ステップ、fuzzing、maximumInterval です。weights を省略すると、選択した FSRS バージョンのプリセットを使います。
#プリセットかカスタム定義か
既定の FSRS モデル・dateChrono・標準のポリシー構成が製品に合うなら DefaultScheduler を使います——最速で正しい出発点です。別のモデルや chrono が必要な場合、ポリシーを増減したい場合、ユーザーごとに検証する設定を公開したい場合は defineScheduler を使います。どちらも最終的には同じスケジューラインスタンス API(newCard、review、rollback、preview、forget)になります。定義とインスタンスのモデルはスケジューラ概要を参照してください。