You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Sep 1, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Sep 1, 2026. It is now read-only.
Single-character template literal inference consumes a full code point in tsgo vs one UTF-16 code unit in tsc #4137
main.ts(4,7): error TS2322: Type '["�", "�abc"]' is not assignable to type '["😀", "abc"]'.
Type at position 0 in source is not compatible with type at position 0 in target.
Type '"�"' is not assignable to type '"😀"'.
This is a real compiler parity issue, though the edge case is very specific. tsgo appears to treat the emoji as one character here, while tsc follows JavaScript string behavior and splits by UTF-16 code units.
The mismatch is real, but the quick fix I tried is not correct enough to PR. The trap is that making tsgo report the same TS2322 diagnostic is easy, but it can still infer the wrong type.
A naive change ends up splitting the UTF-8 byte sequence for 😀, which produces a byte-split artifact rather than matching tsc's UTF-16 code-unit split. tsc is effectively slicing one JavaScript string code unit here, so the expected behavior involves the surrogate halves, not one UTF-8 byte.
From what I can see, tsgo stores checker string literal values as Go strings, so this does not look like a small local tweak in template literal inference. Matching tsc exactly likely needs a representation path that can preserve synthetic UTF-16 surrogate halves, concatenate surrogate pairs back correctly, and print lone halves the same way tsc does.
Activity
danyalahmed1995 commentedon Jun 1, 2026
Ok legit i can reproduce it locally.
This is a real compiler parity issue, though the edge case is very specific.
tsgoappears to treat the emoji as one character here, whiletscfollows JavaScript string behavior and splits by UTF-16 code units.Although this finding looks oddly specific 🤔 .
danyalahmed1995 commentedon Jun 1, 2026
I checked it a bit deeper.
The mismatch is real, but the quick fix I tried is not correct enough to PR. The trap is that making
tsgoreport the sameTS2322diagnostic is easy, but it can still infer the wrong type.A naive change ends up splitting the UTF-8 byte sequence for
😀, which produces a byte-split artifact rather than matchingtsc's UTF-16 code-unit split.tscis effectively slicing one JavaScript string code unit here, so the expected behavior involves the surrogate halves, not one UTF-8 byte.From what I can see,
tsgostores checker string literal values as Go strings, so this does not look like a small local tweak in template literal inference. Matchingtscexactly likely needs a representation path that can preserve synthetic UTF-16 surrogate halves, concatenate surrogate pairs back correctly, and print lone halves the same waytscdoes.jakebailey commentedon Jun 1, 2026
This issue has a wider root cause. Note all of these: https://github.com/microsoft/typescript-go/issues?q=is%3Aissue%20state%3Aopen%20(utf%20OR%20surrogate%20OR%20unicode%20OR%20emoji%20OR%20%22hex%20entity%22%20OR%20%22character%20reference%22%20OR%20%22code%20point%22%20OR%20%22code%20unit%22%20OR%20%22non-ASCII%22%20OR%20BOM)
The right encoding is going to be WTF-8 or something
RyanCavanaugh commentedon Jun 5, 2026
This is now the "correct" behavior per microsoft/TypeScript#63533