Skip to content

createLanguageThis inference collapses productions to unknown (Deno 2.6.8 / TS 5.9.2) #3

@ClaudiuCeia

Description

@ClaudiuCeia

Summary

createLanguageThis is advertised as inference-friendly (so callers can avoid writing explicit language types), but on Deno 2.6.8 (TypeScript 5.9.2) the inferred types for productions referenced via this often collapse to Parser<unknown>. This causes downstream combinators like either(...) / seq(...) to yield unknown values and breaks type-checking.

Versions

  • Deno: 2.6.8
  • TypeScript: 5.9.2 (via Deno)
  • combine: jsr:@claudiu-ceia/combine@0.2.6

Repro

Save as repro.ts:

import {
  createLanguageThis,
  either,
  map,
  number,
  regex,
  seq,
} from "jsr:@claudiu-ceia/combine@0.2.6";

export const Lang = createLanguageThis({
  Literal() {
    return map(regex(/k/i, "k"), () => 1000);
  },
  ShortLiteral() {
    return map(regex(/m/i, "m"), () => 1_000_000);
  },
  Inner() {
    return map(
      seq(number(), either(this.Literal, this.ShortLiteral)),
      ([num, lit]) => num * lit,
    );
  },
  parser() {
    return this.Inner;
  },
});

Run:

deno check repro.ts

Actual

Type error:

TS18046 [ERROR]: 'lit' is of type 'unknown'.

Expected

lit should be inferred as number (since both Literal() and ShortLiteral() return Parser<number>).

Workaround

Provide an explicit defs type via the generic parameter:

import type { Parser } from "jsr:@claudiu-ceia/combine@0.2.6";

type L = {
  Literal: () => Parser<number>;
  ShortLiteral: () => Parser<number>;
  Inner: () => Parser<number>;
  parser: () => Parser<number>;
};

export const Lang2 = createLanguageThis<L>({ /* same body */ });

Notes

This seems to be tied to how createLanguageThis’s signature infers T and then computes BoundFromThisDefs<T> (in src/language.ts). Inference appears to lose the specific return type for methods when those methods are used through this inside other methods.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions