The warning has nothing to do with if_else(), but is purely due to as.numeric("2017:2019"). It doesn't give a warning in the second case because the argument is not evaluated.
I'm afraid if_else() will always evaluates its arguments at once when needed, since everything is vectorized. If you wanted to only evaluate the rows where the false condition is used, you would need to rewrite a non-vectorized version (with for and if).
In your case, I think the best way is to explicitly treat the non-numeric cases as strings before calling as.numeric():
tibble(YearOrig=c(as.character(2015:2019), "2017:2019")) %>%
mutate(YearOrig2 = str_replace(YearOrig, "2017:2019", replacement = "9999"),
Year=if_else(YearOrig2=="9999", 9999, as.numeric(YearOrig2)))
(of course in that example the if_else becomes unnecessary)