import typing


def asBool(key: str, value: typing.Union[str, bool, int]) -> bool:
    """
    Coerce a key to boolean

    Parameters
    ----------
    key : str
        Name of this setting. Used in error reporting
    value : string or bool or int
        Trivial for booleans. If integer, return the corresponding
        value **only** for values of ``1`` and ``0``. If a string,
        values of ``{"1", "yes", "y", "true"}`` denote True, values
        of ``{"0", "no", "n", "false"}`` denote False. Strings are
        case-insensitive

    Raises
    ------
    TypeError
        If the conversion fails

    """
    if isinstance(value, bool):
        return value
    elif isinstance(value, int):
        if value == 0:
            return False
        if value == 1:
            return True
        raise ValueError(
            f"Could not coerce {key}={value} to boolean. Integers "
            "must be zero or one"
        )
    elif isinstance(value, str):
        if value.lower() in {"1", "yes", "y", "true"}:
            return True
        if value.lower() in {"0", "no", "n", "false"}:
            return False
        raise ValueError(
            f"Could not coerce {key}={value} to boolean. Strings must be "
            "0 1 y n yes no true false"
        )

    raise TypeError(f"Could not coerce {key}={value} to boolean")