How do I create a nested Hash type?

Update: I asked in Crystal gitter chat [1] too and got answers which I’m posting here just to capture the info for other newbies:

So in Perl $h{two}{foo} is very compact and not so compact in Crystal in my above example h["two"].as(Hash)["foo"].

However, I learned that if the nested hash has consistent values then Crystal can also do the compact syntax, e.g. h["two"]["foo"]:

$ crystal eval --time --progress --error-trace 'h=Hash{"two" => Hash{"foo" => 3}}; printf %[debug: >#{h}< >%s< >%s<\n], h["two"], h["two"]["foo"];'
debug: >{"two" => {"foo" => 3}}< >{"foo" => 3}< >3<
Execute: 00:00:00.012247333

Further I discovered that Crystal Named Tuples might be used instead of the second level hash key as an alternative compact syntax h["two"].foo which is probably also faster in performance, e.g.:

$ crystal eval --time --progress --error-trace 'record A, foo : Int32; h=Hash{"two" => A.new(foo: 3), "three" => A.new(foo: 4)}; printf %[debug: >#{h}< >%s< >%s<\n], h["two"], h["two"].foo; p! h;'
debug: >{"two" => A(@foo=3), "three" => A(@foo=4)}< >A(@foo=3)< >3<
h # => {"two" => A(@foo=3), "three" => A(@foo=4)}
Execute: 00:00:00.014652016

However, again, if you mix hash value types, even with named tuples, then the syntax gets fat again h["two"].as(NamedTuple)[:foo], e.g.:

$ crystal eval --time --progress --error-trace 'h=Hash{"two" => {foo: 3}, "three" => {foo: 4, bar: "baz"}, "four" => 1}; printf %[debug: >#{h}< >%s< >%s<\n], h["two"], h["two"].as(NamedTuple)[:foo]; p! h;'
debug: >{"two" => {foo: 3}, "three" => {foo: 4, bar: "baz"}, "four" => 1}< >{foo: 3}< >3<
h # => {"two" => {foo: 3}, "three" => {foo: 4, bar: "baz"}, "four" => 1}
Execute: 00:00:00.010379377

[1] https://gitter.im/crystal-lang/crystal