Produce a hash for a type that is unique for that type. The hash takes both actual type names and type structure into account.
The purpose of the hash of a type is to be able to store the type of a persisted value together with the value. By comparing the type hash of a persisted value and the expected value we can know if the persistened value is of the correct type.
The current implementation is not really a hash, but a string representation of the type structure.