I would recommend using TryGetValue instead of Contains() because when you use Contains() you are doing 2 lookups in the dictionary. If you use TryGetValue you can both check if it exists and get the value in one lookup.
if(state.TryGetValue(saveable.GetType().ToString(), out var value)) {
saveable.RestoreState(value);
}