与生俱来的类型安全
同一份 Schema 同时驱动运行时校验与 TypeScript 输入、输出类型推导。
一个面向 TypeScript 的类型安全调度框架。从开箱即用的 FSRS-7 开始,再自由组合模型、时间系统与业务规则,不需要切换到另一套 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
选定模型与时间系统,再逐个叠加产品需要的中间件策略。defineScheduler.use(middleware)
当内置能力不够时,自己编写中间件、时间系统或模型。defineMiddlewaredefineChrono
类型安全
Standard Schema 为配置、卡片、复习日志、记忆状态与时间值提供统一的运行时校验与类型契约。
scheduleStatus: 'new' | 'review' | 'suspended'
内置能力
为卡片添加并维护复习次数(reps)与遗忘次数(lapses)两个计数器。
将配置的目标保留率传入间隔计算。
根据记忆状态和复习成本调整保留率,用于替换固定目标保留率策略。
以卡片 ID 与复习次数为种子,对间隔施加确定性的抖动。
以分钟、小时或天为单位安排学习与重新学习步骤。
每当卡片的遗忘次数达到所配置阈值的整数倍时,暂停该卡片。
将最终调度间隔限制在配置的上限内。
避免更高评分得到更短的调度间隔。
保存安排天数及其撤销所需的旧值,启用小数天数时保留小数间隔。
架构
每一个组件都可以单独替换,而调度内核保持不变。
use() 返回一个新的 definition;已有的 definition 以及由它创建的调度器都不会被改动。
性能
API 围绕惰性求值、代码分割与不可变结果设计。
DefaultScheduler 会按需加载指定的 FSRS 版本,有助于减少初始加载中不需要的模型代码。
preview() 只会计算你真正遍历到的评分。
调度器的 schema 在首次访问时才创建,而不是声明时。
sideEffects 为 false,模型与中间件均以子路径导出提供。
review 返回新卡片,不会修改任何输入。
rollback() 能从 revlog 还原上一张卡片,包括中间件字段。
贡献者
项目中的模型、中间件与各项改进,离不开社区贡献者通过 Pull Request 提供的建议与帮助。
赞助者
每一份赞助都为 ts-fsrs 的持续维护,以及跟进 FSRS 研究进展提供帮助。
默认调度器可以覆盖常见场景;需要时,可以用不同的模型、时间系统与中间件,组合出自己的调度器。