My current method doesn't work but I'm not really sure why
I am saving a custom resource like this:
var w = GameWorld.new(100, 100)
w.add_new_world_item(GROUND_TILE_TYPES[0], Vector2(1, 1))
ResourceSaver.save("res://saves/world_2.tres", w)
GameWorld is a custom resource which looks like this:
extends Resource
class_name GameWorld, "res://world/world_icon.png"
export(int) var width: int = 100
export(int) var height: int = 100
export(Array, Vector2) var gates := []
export(Dictionary) var world_items = {}
export(Array) var world_item_ids = []
func _init(width: int, height: int):
self.width = width
self.height = height
self.gates = get_gate_positions_from_dimensions(width, height)
self.world_items = {}
self.world_item_ids = []
func add_new_world_item(type, position) -> void:
...
And world_items in GameWorld is a dictionary int -> WorldItem which is another CustomResource (no idea if that makes a difference)
The world is correctly saved here:

The contents of this look like:
[gd_resource type="Resource" load_steps=5 format=2]
[ext_resource path="res://world/game_world.gd" type="Script" id=1]
[ext_resource path="res://game/vegetation/item_types/grass_1.tres" type="Resource" id=2]
[ext_resource path="res://world/world_item.gd" type="Script" id=3]
[sub_resource type="Resource" id=1]
script = ExtResource( 3 )
world_item_type = ExtResource( 2 )
position = Vector2( 1, 1 )
[resource]
script = ExtResource( 1 )
width = 100
height = 100
gates = [ Vector2( 50, 0 ), Vector2( 50, 100 ) ]
world_items = {
0: SubResource( 1 )
}
world_item_ids = [ 0 ]
I then have a node which takes in a GameWorld as an exported variable:

And drag world_2 to it like so:

But when running and trying to access world like this I get all kinds of errors which basically amount to world not being an instance of GameWorld
When I call world.get_script() it returns [Object:null]
but if I call it on a newly created GameWorld (via GameWorld.new(..)) I get [GDScript:1239]
And none of the properties/methods are there: print(world.world_items)
fails with Invalid get index 'world_items' (on base: 'Resource').
I don't really understand why I this isn't working; especially because I can generate GameWorld at runtime and populate it but when I try and load it from a .tres file it doesn't think it's a GameWorld anymore? Am I just being dumb?