def promote(
    *types: Union[Var, np.generic, int, float, None]
) -> Tuple[Optional[Var], ...]:
    """
    Apply constant promotion and type promotion to given parameters, creating constants and/or casting.

    None-valued parameters are only kept in for ordering.
    """
    from spox._var import result_type

    promotable = [typ for typ in types if typ is not None]
    if not promotable:
        return typing_cast(Tuple[None, ...], types)

    target_type = result_type(*promotable)

    def _promote_target(obj: Union[Var, np.generic, int, float, None]) -> Optional[Var]:
        if isinstance(obj, (np.generic, int, float)):
            return const(np.array(obj, dtype=target_type))
        elif isinstance(obj, Var):
            return cast(obj, to=target_type)
        assert obj is None
        return obj

    return tuple(typ for typ in map(_promote_target, types))
