What is the most idiomatic way to implement bounds checking in `getindex` for arbitrary types?

Base.@propagate_inbounds function Base.getindex(f::Foo{T}, i::Int) where {T}
     idx = f.y[i]
     Base.@boundscheck idx in eachindex(f.x) || throw(BoundsError(x, idx))
     f.x[idx]
end

julia> function force_getindex(x, i)
           @inbounds x[i]
       end;

julia> x, y = [1, 2, 3], [1, 2, 3];

julia> resize!(x, 2);

julia> foo = Foo(x, y);

julia> foo[1]
1

julia> foo[2]
2

julia> foo[3]
ERROR: BoundsError: attempt to access 2-element Vector{Int64} at index [3]
Stacktrace:
 [1] getindex(f::Foo{Int64}, i::Int64)
   @ Main ./REPL[2]:3
 [2] top-level scope
   @ REPL[12]:1

julia> force_getindex(foo, 3)
3