In Julia, dictionaries, like arrays, are invariant. For example, see this question on the concept as it applies to arrays.
This means that:
julia> Int <: Number
true
but,
julia> Vector{Int} <: Vector{Number}
false
and similarly,
julia> Dict{Int, String} <: Dict{Number, String}
false
However, note that Dict on its own is abstract, so
julia> Dict{Int, String} <: Dict
true
and in the code you provide,
julia> isa(d, Dict)
true
As far as I know, if you want to reason specifically about the pair of types in your dictionary, you will need to reference them explicitly. You can do this using keytype(d) and valtype(d). For example, from your question, note that
julia> keytype(d) <: Tuple
true
Of course, if your dictionary is passed into a function, then you can use Dict{T1, T2} in the function signature, and then just reason about T1 and T2...
EDIT: See @FengyangWang's answer for a neat little syntax shortcut being introduced in v0.6