We now duplicate the effort done in TemplateData by building a separate Lua table that can be loaded with mw.loadData(). Instead we should load the TemplateData directly and translate it into a Lua structure. This is pretty straight forward. It can even be mimicked by transcluding the doc page, stripping it down to the TemplateData, and then converting the resulting JSON to a Lua structure.
Still, I think it is better to make a native method mw.loadTemplateData() that does the necessary checks and avoids heavy transclusions.
A problem with this function is that it ends up between two different extensions. It is a result of using both Extension:TemplateData and Extension:Scribunto, but it does not really belong in either of them.