### Apache Airflow version

2.5.1

### What happened

Context: I am attempting to use [TypedDict](https://docs.python.org/3/library/typing.html#typing.TypedDict) objects to maintain the keys used in DAG params in a single place, and check for key names across multiple DAGs that use the params.
This raises an error with `mypy` as `params` expects an `Optional[Dict]`. Due to the invariance of `Dict`, this does not accept `TypedDict` objects.

What happened: I passed a `TypedDict` to the `params` arg of `DAG` and got a TypeError.

### What you think should happen instead

`TypedDict` objects should be accepted by `DAG`, which should accept `Optional[Mapping[str, Any]]`. 

Unless I'm mistaken, `params` are converted to a `ParamsDict` class and therefore the appropriate type hint is a generic `Mapping` type.

### How to reproduce

Steps to reproduce

```Python
from typing import TypedDict

from airflow import DAG
from airflow.models import Param

class ParamsTypedDict(TypedDict):
    str_param: Param

params: ParamsTypedDict = {
    "str_param": Param("", type="str")
}

with DAG(
    dag_id="mypy-error-dag",
    # The line below raises a mypy error
    # Argument "params" to "DAG" has incompatible type "ParamsTypedDict"; expected "Optional[Dict[Any, Any]]"  [arg-type]
    params=params,  
) as dag:
    pass
```

### Operating System

Amazon Linux

### Versions of Apache Airflow Providers

_No response_

### Deployment

Docker-Compose

### Deployment details

_No response_

### Anything else

_No response_

### Are you willing to submit PR?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

"""
    Class to hold all params for dags or tasks. All the keys are strictly string and values
    are converted into Param's object if they are not already. This class is to replace param's
    dictionary implicitly and ideally not needed to be used directly.
    """
    __version__: ClassVar[int] = 1
    __slots__ = ["__dict", "suppress_exception"]
    def __init__(self, dict_obj: dict | None = None, suppress_exception: bool = False):
        """
        :param dict_obj: A dict or dict like object to init ParamsDict
        :param suppress_exception: Flag to suppress value exceptions while initializing the ParamsDict
        """
        params_dict: dict[str, Param] = {}
        dict_obj = dict_obj or {}
        for k, v in dict_obj.items():
            if not isinstance(v, Param):
                params_dict[k] = Param(v)
            else:
                params_dict[k] = v
        self.__dict = params_dict
        self.suppress_exception = suppress_exception
    def __bool__(self) -> bool: