# Parameter specification and type variable tuple should support bounds

**URL:** <https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068>\
**Category:** Typing\
**Tags:** typing, typing-spec\
**Created:** [April 23, 2026, 5:23am UTC](https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068 "2026-04-23T05:23:51Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![KotlinIsland](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/kotlinisland/32/19433_2.png) [@KotlinIsland](https://discuss.python.org/u/KotlinIsland)\
**Post date:** [April 23, 2026, 5:23am UTC](https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068/1 "2026-04-23T05:23:51Z")

</div>

previous step: [variance](https://discuss.python.org/t/parameter-specifications-should-have-variance/106452)

i propose new syntax and semantics for bounds on tvt/ps type parameters:

```py
# typical forms
class A[T: int, *Ts: int, **P: [int]]: ...
A[
    str, # error
    int, # ok, matching Ts bound
    str, # error, not matching Ts bound
    [str], # error, not matching P bound
]

A[
    int, # ok
    int, # ok, matching Ts bound
    bool, # ok, matching Ts bound
    [int], # ok, matching P bound
]

# tvt unpacked form
class B[*Ts: *tuple[int, str]]: ...

B[
    int, # ok
    int, # error, not subtype of str
    int, # error, too many types
]

```

this behaviour is supported in pycharm 2026.1.2

bounds will require a syntax change in cpython

cpython pr: [gh-148945: add support for bounds on type variable tuples and paramet… by KotlinIsland · Pull Request #148946 · python/cpython · GitHub](https://github.com/python/cpython/pull/148946)

---

<div class="post-metadata">

**Author:** ![jorenham](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jorenham/32/27806_2.png) [@jorenham](https://discuss.python.org/u/jorenham)\
**Post date:** [April 23, 2026, 10:56am UTC](https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068/2 "2026-04-23T10:56:07Z")

</div>

Awesome; this will help a lot for NumPy.

For example, we currently cannot generally express functions that e.g. add or remove a dimension from an array, like `numpy.expand_dims` ([docs](https://numpy.org/doc/stable/reference/generated/numpy.expand_dims.html)), because the shape type has `tuple[int, ...]` as an upper bound. So instead, we work around this by adding overloads for the first couple of dimensions: [numpy/numpy/lib/\_shape\_base\_impl.pyi at a253537e7a06e8e41a96d17b3f0ece62d93071ad · numpy/numpy · GitHub](https://github.com/numpy/numpy/blob/a253537e7a06e8e41a96d17b3f0ece62d93071ad/numpy/lib/_shape_base_impl.pyi#L120-L166)  
But as you can see, that can become pretty messy, and doesn’t work for higher-dimensional arrays.

With this proposal, we’d be able to get rid of most overloads. For example for the `axis: int` case we could write:

```py
def expand_dims[*AxisTs: int, DTypeT: np.dtype](
    a: np.ndarray[tuple[*AxisTs], DTypeT],
    axis: int,
) -> np.ndarray[tuple[*AxisTs, int], DTypeT]

```

There are many more examples like these in NumPy that we could sigificantly simplify with this. These include all reduction functions, for example `np.prod` ([src](https://github.com/numpy/numpy/blob/a253537e7a06e8e41a96d17b3f0ece62d93071ad/numpy/_core/fromnumeric.pyi#L1995-L2234)) and `np.sum` ([src](https://github.com/numpy/numpy/blob/a253537e7a06e8e41a96d17b3f0ece62d93071ad/numpy/_core/fromnumeric.pyi#L2236-L2476)) that currently counts 23 (!) overloads each.

---

<div class="post-metadata">

**Author:** ![duncathan](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/duncathan/32/25521_2.png) [@duncathan](https://discuss.python.org/u/duncathan)\
**Post date:** [April 23, 2026, 2:39pm UTC](https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068/3 "2026-04-23T14:39:17Z")

</div>

What does it mean for a ParamSpec to have a bound? Is that specified somewhere? I don’t see it in the typing documentation, and I’m struggling to read the syntax in the OP intuitively.

---

<div class="post-metadata">

**Author:** ![Jelle](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jelle/32/1049_2.png) [@Jelle](https://discuss.python.org/u/Jelle)\
**Post date:** [April 23, 2026, 4:04pm UTC](https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068/4 "2026-04-23T16:04:16Z")

</div>

It is not specified; the spec currently does not allow bounds for ParamSpec or TypeVarTuple. @KotlinIsland is proposing to change that.

> unpacking in a bound will require a syntax change in cpython

Not just unpacking; native generics do not allow bounds for ParamSpec or TypeVarTuple. Changing this would be a syntax change that we can’t make until Python 3.16.

---

<div class="post-metadata">

**Author:** ![duncathan](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/duncathan/32/25521_2.png) [@duncathan](https://discuss.python.org/u/duncathan)\
**Post date:** [April 23, 2026, 4:38pm UTC](https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068/5 "2026-04-23T16:38:27Z")

</div>

> [@Jelle](#):
>
> It is not specified; the spec currently does not allow bounds for ParamSpec or TypeVarTuple. @KotlinIsland is proposing to change that.

Thanks for clarifying. In that case, I would love some additional elaboration on what’s being proposed for bounds on ParamSpec. I understand the examples for TypeVarTuple and see the value there!

---

<div class="post-metadata">

**Author:** ![jorenham](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jorenham/32/27806_2.png) [@jorenham](https://discuss.python.org/u/jorenham)\
**Post date:** [April 23, 2026, 6:14pm UTC](https://discuss.python.org/t/parameter-specification-and-type-variable-tuple-should-support-bounds/107068/6 "2026-04-23T18:14:47Z")

</div>

> [@Jelle](#):
>
> Changing this would be a syntax change that we can’t make until Python 3.16.

Thanks to `typing_extensions` that shouldn’t matter much for NumPy 🙂
