# Why is Tuple Covariant / NamedTuple is not?

**URL:** <https://discourse.julialang.org/t/why-is-tuple-covariant-namedtuple-is-not/47236>\
**Category:** Internals & Design\
**Tags:** type, tuple, namedtuple\
**Created:** [September 25, 2020, 2:00am UTC](https://discourse.julialang.org/t/why-is-tuple-covariant-namedtuple-is-not/47236 "2020-09-25T02:00:11Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [September 25, 2020, 2:00am UTC](https://discourse.julialang.org/t/why-is-tuple-covariant-namedtuple-is-not/47236/1 "2020-09-25T02:00:11Z")

</div>

Hello everyone,

Here is my situation when you work …

WITH TUPLE

```nohighlight
A = (:a, (2,3))
B = (:b, (2,3,4))

using Test
@test typeof(A) !== typeof(B)

# but, you can catch them with vararg
T = Tuple{Symbol, NTuple{N,Int} where N}
@test A isa T
@test B isa T

```

WHILE WITH NAMEDTUPLE

```nohighlight
NA = (foo=:a, bar=(2,3))
NB = (foo=:b, bar=(2,3,4))

@test typeof(NA) !== typeof(NB)

# and you can not catch them with vararg
NT = NamedTuple{(:foo, :bar),T}
@test_broken NA isa NT
@test_broken NB isa NT

# even broaden them up to tuple fail
T2 = Tuple{Symbol, Tuple}
NT2 = NamedTuple{(:a,:b),T2}
@test_broken NA isa NT2
@test_broken NB isa NT2

# meanwhile covariance still ok @ tuple
@test A isa T2
@test B isa T2

```

* * *

so, aren’t there any fix for now ?

i found one, turning to array.

```nohighlight
NA = (foo=:a, bar=[2,3])
NB = (foo=:b, bar=[2,3,4])

T3 = Tuple{Symbol, Vector{Int}}
NT3 = NamedTuple{(:foo, :bar),T3}
@test NA isa NT3
@test NB isa NT3

```

But i find ugly and a bit counterfeiting.

Is there something better in this case, eg.

- having a supertype with collection fields in namedtuple
- without needing to flip front and back from tuple to vector ?

PS I subodorate that’s may be just a lack of time and review to do it

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [September 25, 2020, 2:06am UTC](https://discourse.julialang.org/t/why-is-tuple-covariant-namedtuple-is-not/47236/2 "2020-09-25T02:06:43Z")

</div>

Just make `NT` covariant on `T`:

```julia
julia> T = Tuple{Symbol, NTuple{N,Int} where N}
Tuple{Symbol,Tuple{Vararg{Int64,N}} where N}

julia> NT = NamedTuple{(:foo, :bar), <:T}
NamedTuple{(:foo, :bar),var"#s46"} where var"#s46"<:Tuple{Symbol,Tuple{Vararg{Int64,N}} where N}

julia> (foo=:a, bar=(2,3)) isa NT
true

```

`Tuple` is the only covariant type in julia, everything else must be made covariant with `<:` if that’s what you want.

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [September 25, 2020, 2:19am UTC](https://discourse.julialang.org/t/why-is-tuple-covariant-namedtuple-is-not/47236/3 "2020-09-25T02:19:33Z")

</div>

Good point. Thanks.

I was used to deal with `<:` on fun sig.  
But is is autonomous and will generate everywhere the good typevar that make it work

FOR MEMO

```nohighlight
NT4 = NamedTuple{(:foo, :bar), <:T} # the NT :)

@test last(Base.unwrap_unionall(NT4).parameters) isa TypeVar
@test (last(Base.unwrap_unionall(NT4).parameters)).ub == T

```
