First, you can take advantage of the fact that DataFrame constructor by default copies columns so you can write:
DataFrame(col_names .=> Ref([]))
Now if you want different element types for columns you can write e.g.:
DataFrame(col_names .=> [T[] for T in [Int, String, Bool, Char]])
or (via a small hack):
DataFrame(col_names .=> rand.([Int, String, Bool, Char], 0))