In Bash if you don't explicitly set an exit code, the exit code of the script will be the exit code of the last command that ran. So it's possible to have a command that failed but the script returns 0 (success) because another command ran successfully after the one that failed. If you add another command to your example for instance, like this
i=0 ; ((i++)) ; echo ; echo $? it will return zero. The return value of
(( is (according to the manual): "If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1." Your example returns 1 because
i++ is evaluated later;
++i will return 0.
(( ... )) is being evaluated arithmetically and does not return an success/error code. This is what the manual has to say about arithmetic: "The operators and their precedence, associativity, and values are the same as in the C language." In C a zero value is considered false whereas anything else is true. In Bash is the reverse, ie. zero is considered "success" whereas anything else is considered an error exit code.
To answer your last question, I think the only way to know if everything works is either to exit the script prematurely with
exit <error_code> or check the exit code after every command with
if [ $? -ne 0 ]; then. Or in this case you can use arithmetic expansion
i=$((i+1)); this will return zero, and in case of error it will return non-zero for example
i=$((i/0)). Alternatively in Bash you cal also add
set -e at the top of the script and it will automatically exit as soon as any command returns a non-zero exit code (this does not seem to work with zsh though).