diff --git a/docs/tutorial/parameter-types/enum.md b/docs/tutorial/parameter-types/enum.md
index 6af834bf54..561e889d0d 100644
--- a/docs/tutorial/parameter-types/enum.md
+++ b/docs/tutorial/parameter-types/enum.md
@@ -66,3 +66,42 @@ Training neural network of type: lstm
```
+
+### Literal choices
+
+With Python 3.8+, you can also use `typing.Literal` to represent a set of possible predefined choices, without having to use an `Enum`:
+
+```Python hl_lines="13"
+{!../docs_src/parameter_types/enum/tutorial003.py!}
+```
+
+
+
+```console
+$ python main.py --help
+
+// Notice the predefined values [simple|conv|lstm]
+Usage: main.py [OPTIONS]
+
+Options:
+ --network [simple|conv|lstm] [default: simple]
+ --install-completion Install completion for the current shell.
+ --show-completion Show completion for the current shell, to copy it or customize the installation.
+ --help Show this message and exit.
+
+// Try it
+$ python main.py --network conv
+
+Training neural network of type: conv
+
+// Invalid value
+$ python main.py --network capsule
+
+Usage: main.py [OPTIONS]
+Try "main.py --help" for help.
+
+Error: Invalid value for '--network': invalid choice: capsule. (choose from simple, conv, lstm)
+```
+
+
+
diff --git a/docs_src/parameter_types/enum/tutorial003.py b/docs_src/parameter_types/enum/tutorial003.py
new file mode 100644
index 0000000000..6271eac338
--- /dev/null
+++ b/docs_src/parameter_types/enum/tutorial003.py
@@ -0,0 +1,11 @@
+from typing import Literal
+
+import typer
+
+
+def main(network: Literal["simple", "conv", "lstm"] = "simple"):
+ typer.echo(f"Training neural network of type: {network}")
+
+
+if __name__ == "__main__":
+ typer.run(main)
diff --git a/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py
new file mode 100644
index 0000000000..700fb469c7
--- /dev/null
+++ b/tests/test_tutorial/test_parameter_types/test_enum/test_tutorial003.py
@@ -0,0 +1,56 @@
+import subprocess
+import sys
+
+import pytest
+import typer
+from typer.testing import CliRunner
+
+pytestmark = pytest.mark.skipif(sys.version_info < (3, 8), reason="requires python3.8")
+
+
+runner = CliRunner()
+
+
+@pytest.fixture(scope="module")
+def mod():
+ from docs_src.parameter_types.enum import tutorial003 as mod
+
+ return mod
+
+
+@pytest.fixture(scope="module")
+def app(mod):
+ app = typer.Typer()
+ app.command()(mod.main)
+ return app
+
+
+def test_help(app):
+ result = runner.invoke(app, ["--help"])
+ assert result.exit_code == 0
+ assert "--network [simple|conv|lstm]" in result.output
+
+
+def test_main(app):
+ result = runner.invoke(app, ["--network", "conv"])
+ assert result.exit_code == 0
+ assert "Training neural network of type: conv" in result.output
+
+
+def test_invalid(app):
+ result = runner.invoke(app, ["--network", "capsule"])
+ assert result.exit_code != 0
+ assert (
+ "Error: Invalid value for '--network': invalid choice: capsule. (choose from simple, conv, lstm)"
+ in result.output
+ )
+
+
+def test_script(mod):
+ result = subprocess.run(
+ ["coverage", "run", mod.__file__, "--help"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ encoding="utf-8",
+ )
+ assert "Usage" in result.stdout
diff --git a/typer/main.py b/typer/main.py
index 02d9a5d7fe..e7f48d2a0d 100644
--- a/typer/main.py
+++ b/typer/main.py
@@ -1,4 +1,6 @@
import inspect
+import sys
+import typing
from datetime import datetime
from enum import Enum
from functools import update_wrapper
@@ -584,6 +586,11 @@ def get_click_type(
[item.value for item in annotation],
case_sensitive=parameter_info.case_sensitive,
)
+ elif sys.version_info >= (3, 8) and typing.get_origin(annotation) == typing.Literal:
+ return click.Choice(
+ tuple(typing.get_args(annotation)),
+ case_sensitive=parameter_info.case_sensitive,
+ )
raise RuntimeError(f"Type not yet supported: {annotation}") # pragma no cover