Skip to content
This repository was archived by the owner on Sep 1, 2026. It is now read-only.
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

Closed as not planned

Description

Steps to reproduce

main.ts:

type Heads<S> = S extends `${infer C}${infer R}` ? [C, R] : never;
type A = Heads<"😀abc">;
declare let a: A;
const chk: ["😀", "abc"] = a;
tsgo main.ts

Behavior with [email protected]

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 '"😀"'.

Behavior with tsgo

No error.

Activity

  1. danyalahmed1995 commented on Jun 1, 2026

    @danyalahmed1995

    Ok legit i can reproduce it locally.

    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.

    Although this finding looks oddly specific 🤔 .

  2. danyalahmed1995 commented on Jun 1, 2026

    @danyalahmed1995

    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 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.

  3. RyanCavanaugh commented on Jun 5, 2026

    @RyanCavanaugh
    Member

    This is now the "correct" behavior per microsoft/TypeScript#63533

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions