ruff/crates/ty_python_semantic/resources/mdtest/directives/assert_never.md
Alex Waygood 7d0c8e045c
Some checks are pending
CI / test ruff-lsp (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
[ty] Infer slightly more precise types for comprehensions (#20111)
2025-08-27 13:21:47 +01:00

3.1 KiB

assert_never

Basic functionality

assert_never makes sure that the type of the argument is Never.

Correct usage

from typing_extensions import assert_never, Never, Any
from ty_extensions import Unknown

def _(never: Never):
    assert_never(never)  # fine

Diagnostics

If it is not, a type-assertion-failure diagnostic is emitted.

from typing_extensions import assert_never, Never, Any
from ty_extensions import Unknown

def _():
    assert_never(0)  # error: [type-assertion-failure]

def _():
    assert_never("")  # error: [type-assertion-failure]

def _():
    assert_never(None)  # error: [type-assertion-failure]

def _():
    assert_never(())  # error: [type-assertion-failure]

def _(flag: bool, never: Never):
    assert_never(1 if flag else never)  # error: [type-assertion-failure]

def _(any_: Any):
    assert_never(any_)  # error: [type-assertion-failure]

def _(unknown: Unknown):
    assert_never(unknown)  # error: [type-assertion-failure]

Use case: Type narrowing and exhaustiveness checking

[environment]
python-version = "3.10"

assert_never can be used in combination with type narrowing as a way to make sure that all cases are handled in a series of isinstance checks or other narrowing patterns that are supported.

from typing_extensions import assert_never, Literal

class A: ...
class B: ...
class C: ...

def if_else_isinstance_success(obj: A | B):
    if isinstance(obj, A):
        pass
    elif isinstance(obj, B):
        pass
    elif isinstance(obj, C):
        pass
    else:
        assert_never(obj)

def if_else_isinstance_error(obj: A | B):
    if isinstance(obj, A):
        pass
    # B is missing
    elif isinstance(obj, C):
        pass
    else:
        # error: [type-assertion-failure] "Argument does not have asserted type `Never`"
        assert_never(obj)

def if_else_singletons_success(obj: Literal[1, "a"] | None):
    if obj == 1:
        pass
    elif obj == "a":
        pass
    elif obj is None:
        pass
    else:
        assert_never(obj)

def if_else_singletons_error(obj: Literal[1, "a"] | None):
    if obj == 1:
        pass
    elif obj is "A":  # "A" instead of "a"
        pass
    elif obj is None:
        pass
    else:
        # error: [type-assertion-failure] "Argument does not have asserted type `Never`"
        assert_never(obj)

def match_singletons_success(obj: Literal[1, "a"] | None):
    match obj:
        case 1:
            pass
        case "a":
            pass
        case None:
            pass
        case _ as obj:
            assert_never(obj)

def match_singletons_error(obj: Literal[1, "a"] | None):
    match obj:
        case 1:
            pass
        case "A":  # "A" instead of "a"
            pass
        case None:
            pass
        case _ as obj:
            # TODO: We should emit an error here, but the message should
            # show the type `Literal["a"]` instead of `@Todo(…)`.
            # error: [type-assertion-failure] "Argument does not have asserted type `Never`"
            assert_never(obj)