julia> v isa AbstractVector{AbstractMyType{T} where T <: Number}
false
The point is that
AbstractVector{AbstractMyType{T} where T <: Number}
is not the same as
AbstractVector{AbstractMyType{T}} where T <: Number
The second one subsumes all AbstractVectors whose element type is some type of the form AbstractMyType{T} where T is a subtype of Number. The first one applies only to AbstractVectors whose element type is exactly AbstractMyType{<:Number}.
But more to your original point, you can add another where clause to say that it can match any subtype of AbstractMyType as long as its parameter is <: Number.
julia> v = [MyType1{Int}(), MyType2{Int}()];
julia> v isa AbstractVector{<:AbstractMyType{<:Number}}
true
A good point, but I would like to note that this also includes types like Vector{MyType{Int}} whose eltype is the concrete MyType{Int}, whereas AbstractVector{AbstractMyType{T}} where {T<:Number} excludes such types. Therefore, the two type specifications are different.
There are cases where this difference matters. For example, I am actually trying to specify the type of v in a function signature as
function myfun(v::AbstractVector{AbstractMyType{T}}) where {T<:Number}
in order to make sure that the eltype of v is always the abstract AbstractMyType, , because myfun is expected to take aways a vector of abstract-type elements.
Why would you want to do that? Coming from generic programming a function taking a vector of AbstractMyTypes could only do some reasonable things with its inputs, such as iterating over the vector and calling some methods on some elements – which would need to work for AbstractMyTypes. In any case, the function should probably also work with vectors holding some concrete subtype such as MyType1.
In OOP this idea is known as the Liskov substitution principle and the related quote by Jon Postel:
be conservative in what you do, be liberal in what you accept from others