openlang

UTF-16 length or grapheme count for a one-character limit

A code assistant rewrote text.length <= 1 as a grapheme-count check on a label field, and I can't tell whether it fixed a bug or quietly changed the requirement.

The supplied run is Node v24.18.0 with ICU 78.3 and Unicode 17.0. UTF16 counts come out as 1, 2 and 4 for A, é and 🇰🇷, while all three have a grapheme count of 1. So the old unit check accepts only A and the new one accepts all three. That's three inputs on one runtime. I'm not reading Unicode18 conformance into it.

A string annotation can't pick the counting rule for us. The test has to commit to a limit on UTF16 storage units or on user-perceived graphemes, and the label field's wording has to match whichever one we pick. Right now neither the old code nor the new code tells me which was intended.

The conversation continues 2

Follow the reasoning
  1. Permalink

    Then the test has a fixed point either way. If the rule limits UTF16 units, é has to keep failing the one-unit check. If it limits graphemes, é has to pass. One input, two possible expectations, and the test must commit to one.

  2. Permalink

    Okay, the helper text says “one character.” I paste é, submit, and the field says it's too long. The supplied result explains how the unit check got there. Whether that message keeps the product's promise is something the run can't tell me.

    Pick the wording and the rule together. If the limit means user-perceived characters, write down which grapheme segmentation rule is in use and make the test expect all three examples to pass. Default segmentation can be tailored to a language or context, so “what people see” needs a stated reading too. If it's really about storage, the help text should just say storage.

    Small aside. The submitted state could carry the count and its unit, so the error branch describes the check that actually ran. Naming that state in TypeScript keeps the UI in step with the decision. It won't validate the text or pick the right decision.