# NTuple type vs conversion inconsistency

**URL:** <https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005>\
**Category:** General Usage\
**Tags:** question, ntuple\
**Created:** [August 23, 2026, 12:00pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005 "2026-08-23T12:00:42Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 23, 2026, 12:00pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/1 "2026-08-23T12:00:42Z")

</div>

I find this a bit weird:

```julia
julia> x = (1, "a fish")
(1, "a fish")

julia> x isa NTuple{2} 
false

julia> NTuple{2}(x) ≡ x
true

```

That is, `T(x) ≡ x` yet `x` is not a `T`.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [August 23, 2026, 12:13pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/2 "2026-08-23T12:13:38Z")

</div>

Expanding out the `NTuple` alias:

```julia-auto
julia> x isa Tuple{Any, Any}
true

julia> Tuple{Any,Any} <: Tuple{T,T} where T
false

```

And the underlying conversion dispatches to `convert(::Type{T}, x::NTuple{N,Any}) where {N, T<:Tuple}`, not sure how much sense any of this makes.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 23, 2026, 12:16pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/3 "2026-08-23T12:16:32Z")

</div>

Just to clarify: I understand _why_ this happens. Each step is rational and makes sense given how Julia works, it’s the bottom line that bothers me.

I have no good suggestion on how to fix this. We could make `NTuple{N}(x)` error unless elements of `x` have the same _concrete_ type, but I that would break a lot of existing code.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [August 23, 2026, 12:19pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/4 "2026-08-23T12:19:21Z")

</div>

If this is a _bona fide_ type constructor bug, they could sweep General for `NTuple{N}` calls and check whether a fix is worth it. Wouldn’t be the first time Julia made a rare “breaking” change.

Kinda unnecessary to say, but I never really liked that tuples are covariant unlike everything else, and I think this is an occasional source of confusion that results in things like this. Wouldn’t things work just as well if tuples were invariant and themselves only allowed concrete type parameters? Maybe there’s a good reason for the notation beyond saving typing `<:`.

---

<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:** [August 23, 2026, 12:20pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/5 "2026-08-23T12:20:28Z")

</div>

I wonder if it would be breaking to instead find a way to migrate `NTuple{2}` to mean `Tuple{Any, Any}`, rather than `Tuple{T, T} where {T <: Any}`.

This might require some nasty special casing, but maybe there’s a nice way 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:** [August 23, 2026, 12:24pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/6 "2026-08-23T12:24:27Z")

</div>

> [@Tamas\_Papp](#):
>
> We could make `NTuple{N}(x)` error unless elements of `x` have the same _concrete_ type, but I that would break a lot of existing code.

This is something that a lot of people have been wishing for in various forms for a long time.

Essentially the general invariant people want is that for a type `T`, then `T(args...)` should always produce a `T`. The general case of this would be massively breaking, but I think is something that at the very least should be set aside as a 2.0 milestone issue.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [August 23, 2026, 12:27pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/7 "2026-08-23T12:27:57Z")

</div>

> [@Mason](#):
>
> migrate `NTuple{2}` to mean `Tuple{Any, Any}`

I don’t think that the omitted `NTuple` parameter being `Any` would be an intuitive exception, on top of tuple types being unusual already.

---

<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:** [August 23, 2026, 12:42pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/8 "2026-08-23T12:42:23Z")

</div>

> [@Benny](#):
>
> I don’t think that the omitted `NTuple` parameter being `Any` would be an intuitive exception, on top of tuple types being unusual already.

There’s more options here than changing what it means to omit a parameter. `NTuple` is a very special object that expands with special cased semantics that users can’t replicate themselves in another type.

I’m _speculating_ that we could maybe tweak how it expands out into a `Tuple` without wreaking too much havok. Currently when you write `NTuple{3}`, this first turns into `NTuple{3, T} where {T}` and then into `Tuple{T, T, T} where {T}`, but it’s not actually obvious to me that this should be the case.

We could _also_ make this mean `NTuple{T where {T}, U, where {U}, V where {V}}` by flipping the order at which we expand that special semantic. I suspect we don’t want to do this for a number of reasons, but it’s maybe worth pondering

(but probably not, I’m just spitballing, which maybe I shouldnt do)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 23, 2026, 12:47pm UTC](https://discourse.julialang.org/t/ntuple-type-vs-conversion-inconsistency/139005/9 "2026-08-23T12:47:12Z")

</div>

> [@Mason](#):
>
> `NTuple` is a very special object

I don’t think it is, it is [just a type alias](https://github.com/JuliaLang/julia/blob/08eef7536a689b78115ac218645f66b6d0e3305a/base/boot.jl#L747).

Nothing is special cased about `NTuple` _per se_.
