def as_shared_dtype(scalars_or_arrays, xp=None):
    """Cast arrays to a shared dtype using xarray's type promotion rules."""
    if any(is_extension_array_dtype(x) for x in scalars_or_arrays):
        extension_array_types = [
            x.dtype for x in scalars_or_arrays if is_extension_array_dtype(x)
        ]
        non_nans = [x for x in scalars_or_arrays if not isna(x)]
        if len(extension_array_types) == len(non_nans) and all(
            isinstance(x, type(extension_array_types[0])) for x in extension_array_types
        ):
            return [
                x
                if not isna(x)
                else PandasExtensionArray(
                    type(non_nans[0].array)._from_sequence([x], dtype=non_nans[0].dtype)
                )
                for x in scalars_or_arrays
            ]
        raise ValueError(
            f"Cannot cast values to shared type, found values: {scalars_or_arrays}"
        )

    # Avoid calling array_type("cupy") repeatidely in the any check
    array_type_cupy = array_type("cupy")
    if any(isinstance(x, array_type_cupy) for x in scalars_or_arrays):
        import cupy as cp

        xp = cp
    elif xp is None:
        xp = get_array_namespace(scalars_or_arrays)

    # Pass arrays directly instead of dtypes to result_type so scalars
    # get handled properly.
    # Note that result_type() safely gets the dtype from dask arrays without
    # evaluating them.
    dtype = dtypes.result_type(*scalars_or_arrays, xp=xp)

    return [asarray(x, dtype=dtype, xp=xp) for x in scalars_or_arrays]
Cast arrays to a shared dtype using xarray's type promotion rules.
xarray/core/duck_array_ops.py