#Quick start
Migrating an existing application? Follow the v5 → v6 and FSRS-7 migration guide.
#Installation
ts-fsrs requires Node.js 24 or later.
npm install ts-fsrsyarn add ts-fsrspnpm add ts-fsrsbun add ts-fsrsdeno add npm:ts-fsrsInstall @open-spaced-repetition/binding separately only when you need to train FSRS parameters or convert review-log CSV files.
#Start with DefaultScheduler
DefaultScheduler() is the fastest way to add FSRS scheduling. It defaults to FSRS-7 and includes the standard retention, statistics, learning-step, maximum-interval, monotonic-interval, and scheduled-days policies; fuzzing is available as an option.
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
)
)
The example makes the common defaults explicit. Change desiredRetention, learning and relearning steps, fuzzing, or maximumInterval for your product; omit weights to use the preset for the selected FSRS version.
#Create a scheduler
Use defineScheduler when you need to choose the model, chronology, or middleware yourself. It creates a reusable definition; calling .create() validates the configuration and returns an independent scheduler.
chrono defines how time is represented, stored on cards and review logs, and used in scheduling calculations, allowing you to use JavaScript Date, Temporal, or numeric time values. chrono.normalize uses a ChronoTimeNormalizer schema to convert card or revlog time fields into { previous, current } for scheduling and rollback.
import { const dateChrono: 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;
};
}>;
};
}>
dateChrono , function defineScheduler<const M extends AnyModel, const C extends AnyChrono>(definition: {
readonly model: M;
readonly chrono: C;
}): CustomScheduler<SchedulerNameOf<M>, SchedulerEnvFor<M, C, readonly []>, M, C>
defineScheduler , 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'
import { const FSRS7_DEFAULT_WEIGHTS: number[] FSRS7_DEFAULT_WEIGHTS , const FSRS7Model: Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>
FSRS7Model } from 'ts-fsrs/models/fsrs-7'
// Reuse this definition as the program's scheduling preset.
const const schedulerDefinition: CustomScheduler<"fsrs-7", SchedulerEnvFor<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>, readonly []>, Model<...>, Chrono<...>>
schedulerDefinition = defineScheduler<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>>(definition: {
...;
}): CustomScheduler<...>
defineScheduler ({
model: Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>
model : const FSRS7Model: Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>
FSRS7Model ,
chrono: 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;
};
}>;
};
}>
chrono : const dateChrono: 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;
};
}>;
};
}>
dateChrono ,
})
// Create an independent scheduler when a user's config is available.
const const scheduler: SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>, readonly []>>, ModelCore<...>, ChronoCore<...>>
scheduler = const schedulerDefinition: CustomScheduler<"fsrs-7", SchedulerEnvFor<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>, readonly []>, Model<...>, Chrono<...>>
schedulerDefinition .CustomScheduler<"fsrs-7", SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, Model<...>, Chrono<...>>.create: (ctx: {
readonly config: SchedulerConfigInput<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>, readonly []>;
}) => SchedulerCore<...>
create ({
config: SchedulerConfigInput<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>, readonly []>
config : {
weights: const FSRS7_DEFAULT_WEIGHTS: number[] FSRS7_DEFAULT_WEIGHTS ,
fractionalDays: true,
},
})
const now = new Date('2026-01-01T00:00:00.000Z')
const const card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
}
card = const scheduler: SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>, readonly []>>, ModelCore<...>, ChronoCore<...>>
scheduler .SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>>, ModelCore<...>, ChronoCore<...>>.newCard: (options?: {
readonly now?: Date | undefined;
} | undefined) => {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
}
newCard ({ now })
const const result: {
card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
};
revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
};
}
result = const scheduler: SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<Model<{
readonly name: "fsrs-7";
readonly config: SRSSchema<{
input: {
readonly weights: readonly number[];
};
output: {
readonly weights: readonly number[];
};
}>;
readonly memoryState: SRSSchema<{
input: {
stabilityFast: number;
stability: number;
difficulty: number;
};
output: {
stabilityFast: number;
stability: number;
difficulty: number;
};
}>;
readonly algorithm: FSRS7Algorithm;
}>, Chrono<...>, readonly []>>, ModelCore<...>, ChronoCore<...>>
scheduler .SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>>, ModelCore<...>, ChronoCore<...>>.review: (input: {
readonly card: Readonly<Omit<Readonly<{
stabilityFast: number;
stability: number;
difficulty: number;
} & {
dueAt: Date;
lastReviewAt: Date | null;
} & SchedulerCoreFields$1<"new" | "learning" | "review">>, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>;
readonly grade: Grade;
readonly now?: Date | undefined;
}) => {
card: {
stabilityFast: number;
... 5 more ...;
scheduleStatus: "new" | ... 1 more ... | "review";
};
revlog: {
...;
};
}
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: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
};
revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
};
}
result .card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
}
card .state,
dueAt: const result: {
card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
};
revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
};
}
result .card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
}
card .dueAt,
stability: const result: {
card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
};
revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
};
}
result .card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
}
card .stability,
difficulty: const result: {
card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
};
revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
};
}
result .card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
}
card .difficulty,
stabilityFast: const result: {
card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
};
revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
};
}
result .card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
}
card .stabilityFast,
rating: const result: {
card: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
state: State;
scheduleStatus: "new" | "learning" | "review";
};
revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
};
}
result .revlog: {
stabilityFast: number;
stability: number;
difficulty: number;
dueAt: Date;
lastReviewAt: Date | null;
reviewTime: Date;
state: State;
scheduleStatus: "new" | "learning" | "review";
rating: Grade;
}
revlog .rating,
},
null,
2
)
)
Keep the result of defineScheduler(...), including any middleware added with .use(...), as a program-level preset. Call schedulerDefinition.create({ config }) when a user or collection needs a scheduler; each call validates that configuration and returns an independent instance.
Use the code block's copy button to copy the original source, or run it directly in the dedicated Worker. The fixed now value keeps the output reproducible.
newCard()creates the scheduler's default card shape.review()returns a new card and revlog without mutating the input card.- Add policy middleware with
.use(...)to the reusable definition before creating user-specific schedulers.