+TypeScript example
History management retains snapshots, while TextEditor owns their contents and restoration. This preserves past state without exposing the editor’s internal text to the caretaker.
type ISnapshot = Readonly<{ kind: "snapshot" }>;
// Keep interpretation and restoration of saved state inside the original editor.
class TextEditor {
#text = "";
readonly #snapshots = new WeakMap<ISnapshot, string>();
get text(): string { return this.#text; }
write(text: string): void { this.#text = text; }
// Return only a storage token and retain the actual text privately.
save(): ISnapshot {
const token = Object.freeze({ kind: "snapshot" as const });
this.#snapshots.set(token, this.#text);
return token;
}
restore(snapshot: ISnapshot): boolean {
const text = this.#snapshots.get(snapshot);
if (text === undefined) return false;
this.#text = text;
return true;
}
}
const editor = new TextEditor();
editor.write("draft");
const saved = editor.save();
editor.write("new");
console.log(editor.restore(saved));
console.log(editor.text);
console.log(new TextEditor().restore(saved));
true
draft
false
An immutable token and an editor-private WeakMap hide snapshot contents in this version. A look-alike token or a token from another editor cannot restore its state.