內建型別安全
同一份 Schema 同時負責執行階段驗證,以及 TypeScript 輸入與輸出型別推導。
一個用於 TypeScript 的型別安全排程框架。從開箱即用的 FSRS-7 開始,再自由組合模型、時間系統與 middleware,無須切換到另一套 API。
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 } from 'ts-fsrs'
const createdAt = new Date('2026-01-01T00:00:00.000Z')
export const now = new Date('2026-01-02T09:30:00.000Z')
export const const scheduler: DefaultScheduler<"FSRS-7"> scheduler = await DefaultScheduler<"FSRS-7">(options?: DefaultSchedulerOptions<"FSRS-7"> | undefined): Promise<DefaultScheduler<"FSRS-7">> DefaultScheduler ({
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.desiredRetention?: number | undefined desiredRetention : 0.9,
})
export 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: 'landing-demo',
now: createdAt,
})
// One `{ grade, card, revlog }` row per grade — the panel renders exactly this.
export const const outcomes: PreviewResult<{
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;
};
}>
outcomes = const scheduler: DefaultScheduler<"FSRS-7"> scheduler .preview: (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 now?: Date | undefined;
}) => PreviewResult<...>
preview ({ card, now })同一份 Schema 同時負責執行階段驗證,以及 TypeScript 輸入與輸出型別推導。
從預設排程器開始,在同一核心上逐步替換模型、時間系統與排程策略。
惰性預覽、依版本分割程式碼,以及支援 tree shaking 的子路徑匯出。
漸進式 API
直接使用預設 FSRS 排程器、組合自己的排程策略,或實作全新模型 — 全部共用同一核心。
DefaultScheduler 提供具備合理預設值的 FSRS 排程器,支援 FSRS-3 至 FSRS-7,預設使用 FSRS-7。DefaultScheduler
選擇模型與時間系統,再逐一加入產品需要的 middleware 策略。defineScheduler.use(middleware)
內建能力不足時,自行撰寫 middleware、時間系統或模型。defineMiddlewaredefineChrono
型別安全
Standard Schema 為設定、卡片、複習日誌、記憶狀態與時間值提供統一的執行階段驗證與型別契約。
scheduleStatus: 'new' | 'review' | 'suspended'
內建功能
為卡片加入並維護複習次數(reps)與遺忘次數(lapses)。
將設定的目標保留率傳入間隔計算。
依記憶狀態與複習成本調整保留率,用於取代固定目標保留率策略。
以卡片 ID 與複習次數為種子,套用確定性的間隔變化。
以分鐘、小時或天為單位安排學習與重新學習步驟。
每當卡片的遺忘次數達到設定閾值的整數倍時,就暫停該卡片。
將最終排程間隔限制在設定上限內。
避免較高評分得到較短的排程間隔。
儲存排程天數及復原所需的舊值,啟用小數天數時保留小數間隔。
架構
各個元件彼此相容。
use() 會回傳新的 definition;既有 definition 與由它建立的排程器都不會被改動。
效能
API 以惰性求值、程式碼分割與不可變結果為設計核心。
DefaultScheduler 會依需求載入指定的 FSRS 版本,避免初始載入未使用的模型程式碼。
preview() 只會為實際迭代到的評分進行排程。
排程器的 schema 會在第一次存取時才建立,而非在宣告時建立。
sideEffects 為 false,模型與 middleware 皆提供子路徑匯出。
review 會回傳新卡片,不會修改任何輸入。
rollback() 可從 revlog 還原卡片先前的狀態,包括 middleware 欄位。
貢獻者
專案中的模型、middleware 與各項改進,都受益於社群透過 Pull Request 提供的想法與貢獻。
贊助者
每一份贊助都支持 ts-fsrs 的持續維護,以及與 FSRS 研究進展保持同步。
預設排程器可涵蓋常見情境;需要時,可以用不同的模型、時間系統與 middleware 組合自己的排程器。