It is worth referring to the specification.
When calculating EqualityExpression == RelationalExpression , the values of the left and right parts are obtained, and the Abstract Equality Comparison is applied to them.
Comparing x == y, where x and y are values, returns true or false . Such a comparison is made as follows:
If Type (x) is the same as Type (y) , then the result of executing Strict Equality Comparison x === y is returned.
If x is null and y is undefined , return true .
If x is undefined and y is null , return true .
If Type (x) is Number and Type (y) is String , return the result of the expression x == ToNumber (y) .
If Type (x) is String and Type (y) is Number , return the result of the expression ToNumber (x) == y .
If Type (x) is Boolean , return the result of the expression ToNumber (x) == y .
If Type (y) is Boolean , return the result of the expression x == ToNumber (y) .
If Type (x) is one of the following: String , Number , or Symbol and Type (y) is Object , return the value of the expression x == ToPrimitive (y) .
If Type (x) is Object and Type (y) is one of the following: String , Number , or Symbol , return the value of the expression ToPrimitive (x) == y .
Return false .
Consider the first example:
true == "0"
This expression corresponds to the branch
If Type (x) is Boolean , return the result of the expression ToNumber (x) == y .
When casting to a number, we get the expression: 1 == "0"
we fall into the branch
If Type (x) is Number and Type (y) is String , return the result of the expression x == ToNumber (y) .
When casting to a number, we get the expression: 1 == 0 and as a result: false .
With the second case, the same happens.
Now consider the third case.
Refer again to the specification :
The ToBoolean function is applied to the expression inside the brackets, which in the case of a string, returns false if the string is empty (the length of the string is 0), and true otherwise.
Since "0" is not empty (the length of string 1), the condition is considered fulfilled.