Short answer: Indeed, you can't.
Better longer answer is that you can ONLY save primitive objects to Memory. As stated in the documentation, this is because at the end of each Tick, Memory is serialized by JSON.stringify and the resulting string is saved to the backend.
On the next tick, the backend gives back a plain string which is passed to JSON.parse to produce the Memory object available to your script.
For this reason, you cannot save any class instances, functions, or Game Object references to Memory as JSON.parse will not know how to reinstantiate the class/function on the next tick.
The usual solutions are to save Game Object Ids (e.g. Memory.mainSpawnId = Game.spawns.Spawn1.id). Ids are strings, and will be returned from memory on the next tick, and you can look up the Game Object instance on that tick with: const spawn = Game.getObjectById(Memory.mainSpawnId)
You should save to Memory just enough primitive information to reinstantiate your needed classes on later ticks.
Unrelated to the Memory object, there is another caching technique where you cache real object instances on the Global scope. (e.g. global.MainClass = new MyClass())
This object actually will survive the Tick, as it exists in your virtual javascript instance on the server. (However, I believe you cannot store actual Game Objects (e.g. Creeps, Structures, etc) this way, as they are regenerated every tick by the runtime).
However, while Memory has a system guarantee to ALWAYS survive till the next tick, Global scope has no such guarantee. And anything saved on Global Scope can be cleared without warning by the Runtime if it restarts your isolated VM. (see: https://wiki.screepspl.us/index.php/Global_reset). This is what Smokeman is referring to as you should only store data on Global Scope that you can regenerate/recalculate from the information you have in Memory.
Combining these two techniques efficiently is a large part of optimizing Screeps