title: Why do Unicode emoji property escapes match numbers?
body: <p>I found this awesome way to detect emojis using a regex that doesn't use &quot;huge magic ranges&quot; by using a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes" rel="noreferrer">Unicode property escape</a>:</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>console.log(/\p{Emoji}/u.test('flowers ')) // true
  console.log(/\p{Emoji}/u.test('flowers')) // false</code></pre>
  </div>
  </div>
  </p>
  <p>But when I shared this knowledge <a href="https://stackoverflow.com/a/64007175/8186898">in this answer</a>, @Bronzdragon noticed that <code>\p{Emoji}</code> also matches numbers! Why is that? Numbers are not emojis?</p>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>console.log(/\p{Emoji}/u.test('flowers 123')) // unexpectdly true
  
  // regex-only workaround by @Bonzdragon
  const regex = /(?=\p{Emoji})(?!\p{Number})/u;
  console.log(
    regex.test('flowers'), // false, as expected
    regex.test('flowers 123'), // false, as expected
    regex.test('flowers 123 '), // true, as expected
    regex.test('flowers '), // true, as expected
  )
  
  // more readable workaround
  const hasEmoji = str =&gt; {
    const nbEmojiOrNumber = (str.match(/\p{Emoji}/gu) || []).length;
    const nbNumber = (str.match(/\p{Number}/gu) || []).length;
    return nbEmojiOrNumber &gt; nbNumber;
  }
  console.log(
    hasEmoji('flowers'), // false, as expected
    hasEmoji('flowers 123'), // false, as expected
    hasEmoji('flowers 123 '), // true, as expected
    hasEmoji('flowers '), // true, as expected
  )</code></pre>
  </div>
  </div>
  </p>