Dynamic typing is not idiomatic Go. One option is to always use a map[string]interface{} and then you insert values that are also map[smtring]interface{} to the desired depth. You can use type assertions on the values returned from the map. Another option is to build types via reflect.MapOf. Reflection is a pain.
I’m far from an expert on these things, but this strikes me as something that needs rethinking. I can’t tell you how many times I’ve been trying to do something and over-designed it, trying to do backflips when all I needed was a step.
The only type you need is a map[string]interface{}, lets call that T:
Whenever you want to instantiate an object (of an N dimensions map) you call an New(n int) method, which in a loop creates an object of type T, and adds to it a key value pair where the value is also an object of type T, and so on.
whenever you want to check if two objects of type T have the same number dimensions, just iterate on both and see how many nested keys they have; write a method Dimensions(t T) int