If an if
's condition is a responds_to?
test, in the then
branch the type of a variable is guaranteed to be restricted to the types that respond to that method:
if a.responds_to?(:abs)
# here a's type will be reduced to those responding to the 'abs' method
end
Additionally, in the else
branch the type of the variable is guaranteed to be restricted to the types that don’t respond to that method:
a = some_condition ? 1 : "hello"
# a : Int32 | String
if a.responds_to?(:abs)
# here a will be Int32, since Int32#abs exists but String#abs doesn't
else
# here a will be String
end
The above doesn’t work with instance variables or class variables. To work with these, first assign them to a variable:
if @a.responds_to?(:abs)
# here @a is not guaranteed to respond to `abs`
end
a = @a
if a.responds_to?(:abs)
# here a is guaranteed to respond to `abs`
end
# A bit shorter:
if (a = @a).responds_to?(:abs)
# here a is guaranteed to respond to `abs`
end