To do this I would use dynamic types (via Data.Dynamic).
There are more typeful ways to deal with heterogeneous structures[*],
but if "clients can easily extend it with their own new types" you've
pretty much defined what dynamic types solve.
[*] See the HList papers and library and various solutions to the
"expression problem".