diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d76398448..7f85bef55f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -140,6 +140,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2843](https://github.com/Pycord-Development/pycord/pull/2843)) - Fixed `TypeError` when using `@option` with certain annotations and along with `channel_types`. ([#2835](https://github.com/Pycord-Development/pycord/pull/2835)) +- Fixed `TypeError` when using `Optional[...]` or `... | None` in command option type. + ([#2852](https://github.com/Pycord-Development/pycord/pull/2852)) ### Changed diff --git a/discord/commands/options.py b/discord/commands/options.py index 0425137aed..a88807f893 100644 --- a/discord/commands/options.py +++ b/discord/commands/options.py @@ -26,8 +26,9 @@ import inspect import logging +import types from enum import Enum -from typing import TYPE_CHECKING, Literal, Optional, Type, Union +from typing import TYPE_CHECKING, Literal, Optional, Type, Union, get_args from ..abc import GuildChannel, Mentionable from ..channel import ( @@ -196,6 +197,7 @@ def __init__( if self.name is not None: self.name = str(self.name) self._parameter_name = self.name # default + input_type = self._strip_none_type(input_type) self._raw_type: InputType | tuple = input_type enum_choices = [] @@ -365,6 +367,26 @@ def __init__( if input_type is None: raise TypeError("input_type cannot be NoneType.") + @staticmethod + def _strip_none_type(input_type): + if input_type is type(None): + raise TypeError("Option type cannot be only NoneType") + + if isinstance(input_type, (types.UnionType, tuple)): + args = ( + get_args(input_type) + if isinstance(input_type, types.UnionType) + else input_type + ) + filtered = tuple(t for t in args if t is not type(None)) + if not filtered: + raise TypeError("Option type cannot be only NoneType") + if len(filtered) == 1: + return filtered[0] + return filtered + + return input_type + def to_dict(self) -> dict: as_dict = { "name": self.name,