I’m using this test client side:
if (navigator.userAgent.match(/Mac/) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2) {
...must be iPad OS...
Since there’s no official touch screen for Mac, it seems pretty safe. The actual value of maxTouchPoints on the iPad is 5, BTW.