The dictionary answers are flexible, but we can do one better if we want basic types only:
public static class TypeNameExtensions
{
private static readonly string[] TypeAliases = {
"void", // 0
null, // 1 (any other type)
"DBNull", // 2
"bool", // 3
"char", // 4
"sbyte", // 5
"byte", // 6
"short", // 7
"ushort", // 8
"int", // 9
"uint", // 10
"long", // 11
"ulong", // 12
"float", // 13
"double", // 14
"decimal", // 15
null, // 16 (DateTime)
null, // 17 (-undefined- presumably TimeSpan in some pre-1.0 C# alpha)
"string", // 18
};
If you don't need to support array types:
public static bool TryGetNameAlias(this Type t, out string alias)
=> (alias = TypeAliases[(int)Type.GetTypeCode(t)]) != null && !t.IsEnum;
Edit: If you need to support array types:
public static bool TryGetNameAlias(this Type t, out string alias)
{
string arrayBrackets = null;
while (t.IsArray)
{
arrayBrackets += "[" + new string(',', t.GetArrayRank() - 1) + "]";
t = t.GetElementType();
}
alias = TypeAliases[(int)Type.GetTypeCode(t)];
if (alias == null || t.IsEnum)
return false;
alias += arrayBrackets;
return true;
}
}
This is based on the TypeCode enum:
https://docs.microsoft.com/en-us/dotnet/api/system.typecode?view=netstandard-1.3
which has been around since .Net 1.1
Should be faster than a dictionary since it jumps straight into an array using the TypeCode as index.
The only downside is that we would need an extra check if we want to alias Object as object.
If you are wondering why this enum exist, it's used to facilitate performant implementation of System.IConvertible - which also exposes the GetTypeCode() method:
https://docs.microsoft.com/en-us/dotnet/api/system.iconvertible.gettypecode?view=netstandard-1.3
So in essence it could be seen as an implementation detail that someone one the original C# dev team decided to make public for one reason or another all the way back in the v1.1 days. Perhaps so that others could take advantage of it if they too needed to implement performant fiddling about with the built in types?
Either way it has been part of the language since its early beginnings, over 20 years now! :D
(Personally I have leveraged TypeCode to built a small library for generic numeric range checking and other numeric-specific metadata methods, e.g. performing arithmetic using compile-time unknown generic numeric types without the use of reflection or try-catch attempts.)
Edit: Updated to support array types (including nested and multi-dimensional).
Edit: Updated to properly handle enum types.