Skip to content

NamedTuple parametrized with a ParamSpec can't be used as an annotation #19658

Open

Description

@sbrudenell

Bug Report

NamedTuple parametrized with a ParamSpec can't be used as an annotation.

It's probably easiest to look at my repro to see what I mean.

I know that generic support for NamedTuple is new-ish as of 3.11, but I couldn't find any documentation that says ParamSpec is somehow still unsupported.

To Reproduce

from collections.abc import Callable
from typing import NamedTuple


class T[**P](NamedTuple):
    plugin: Callable[P, int]


def f[**P](a: T[P]) -> None:
    pass

I note that if I change T from a NamedTuple to a dataclass, there's no error.

Expected Behavior

$ mypy t.py                     
Success: no issues found in 1 source file

Actual Behavior

$ mypy t.py
t.py:9: error: Invalid location for ParamSpec "P"  [valid-type]
t.py:9: note: You can use ParamSpec as the first argument to Callable, e.g., "Callable[P, int]"
Found 1 error in 1 file (checked 1 source file)

The error is referring to the T[P] annotation.

Your Environment

  • Mypy version used: mypy 1.17.1 (compiled: yes)
  • Mypy command-line flags: mypy
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: Python 3.13.5

Activity

  1. sterliakov commented on Aug 14, 2025

    @sterliakov
    Collaborator

    mypy/mypy/typeanal.py

    Lines 865 to 881 in b17027e

    if tup is not None:
    # The class has a Tuple[...] base class so it will be
    # represented as a tuple type.
    if info.special_alias:
    return instantiate_type_alias(
    info.special_alias,
    # TODO: should we allow NamedTuples generic in ParamSpec?
    self.anal_array(args, allow_unpack=True),
    self.fail,
    False,
    ctx,
    self.options,
    use_standard_error=True,
    )
    return tup.copy_modified(
    items=self.anal_array(tup.items, allow_unpack=True), fallback=instance
    )

    I guess the answer to this "TODO" (and for TypedDict below too) should be "yes"...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions