How come the comparison between string and number works?

Tell us what’s happening:
You can see, in the ternary operation of the solution, it is comparing

(this.state.userAge >= 18 ? buttonTwo : buttonThree)

But it is clear that this.state.userAge is a string (I logged out the type by using typeof to verify that. I do not understand why a casting or parsing (e.g. parseInt or parseFloat is not needed before comparison?

  **Your code so far**
const inputStyle = {
width: 235,
margin: 5
};

class CheckUserAge extends React.Component {
constructor(props) {
  super(props);
  // Change code below this line
  this.state = {
    input: '',
    userAge: ''
  };
  // Change code above this line
  this.submit = this.submit.bind(this);
  this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
  this.setState({
    input: e.target.value,
    userAge: ''
  });
}
submit() {
  console.log(typeof this.state.userAge);
  this.setState(state => ({
    userAge: state.input
  }));
  console.log(typeof this.state.userAge);
      console.log( this.state.userAge > 18);
}

render() {
  const buttonOne = <button onClick={this.submit}>Submit</button>;
  const buttonTwo = <button>You May Enter</button>;
  const buttonThree = <button>You Shall Not Pass</button>;
  return (
    <div>
      <h3>Enter Your Age to Continue</h3>
      <input
        style={inputStyle}
        type='number'
        value={this.state.input}
        onChange={this.handleChange}
      />
      <br />
      {/* Change code below this line */}
      {
        this.state.userAge === '' ? buttonOne : 
        (this.state.userAge >= 18 ? buttonTwo : buttonThree)
      }
      {/* Change code above this line */}
    </div>
  );
}
}
  **Your browser information:**

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36

Challenge: Use a Ternary Expression for Conditional Rendering

Link to the challenge:

the magics of JavaScript
this.state.userAge is type-coerced to number