Skip to content

TypeScript 7.x removes the classic Program/TypeChecker API that ts-resolver.ts depends on #2106

Description

@carlos-alm

Found while reviewing PR #2093 (dependabot/npm_and_yarn/typescript-7.0.2, bumping typescript devDependency from 6.0.3 to 7.0.2).

Root cause

TypeScript 7.0 is the native/Go-ported compiler rewrite. Its npm package restructures package.json exports:

"exports": {
  ".": "./lib/version.cjs",
  "./unstable/sync": "./dist/api/sync/api.js",
  "./unstable/async": "./dist/api/async/api.js",
  ...
}

The "." entry point — what import ts from 'typescript' resolves to — now only exports { version, versionMajorMinor }. The classic in-process, synchronous Compiler API (ts.createProgram, ts.Program, ts.TypeChecker, ts.sys, ts.readConfigFile, ts.parseJsonConfigFileContent, ts.forEachChild, ts.isIdentifier, etc.) has been removed from the package entirely — verified there is no readConfigFile/createProgram anywhere in the shipped lib/ or dist/ at all, not even as an unexported internal.

In its place, TS 7 ships an out-of-process, RPC-based API under typescript/unstable/sync and typescript/unstable/async (API, Client, Snapshot, Project, Program, Checker, NodeHandle, ...) that spawns/talks to a separate compiler process and returns proxy objects (NodeHandle, Symbol, TypeObject) fetched over a wire protocol, rather than raw AST nodes you can walk directly.

Impact

src/domain/graph/resolver/ts-resolver.ts ("Phase 8.1: TypeScript-native type resolver") is built entirely around the old synchronous, in-process model: it calls ts.readConfigFile/ts.sys/ts.parseJsonConfigFileContent to build compiler options, ts.createProgram(...) to get a Program, program.getTypeChecker() to get a TypeChecker, and then walks the tree-sitter-adjacent AST directly with ts.forEachChild, ts.isIdentifier, ts.isCallExpression, etc., querying the checker synchronously per-node (checker.getTypeAtLocation(node)).

None of this maps onto the new client/server model without a substantial redesign:

  • No more direct SourceFile/Node walking — the new API returns NodeHandle proxies you resolve() against a Project, fetched from a spawned server.
  • No more synchronous single-call checker.getTypeAtLocation(node) — every checker operation is a request to an external process.
  • Config resolution (readConfigFile/parseJsonConfigFileContent) has no equivalent surface in the new API; the closest analog is API.parseConfigFile, which returns a different shape.

Compile-time: bumping to typescript@7.x makes tsc fail outright — every CI job that runs npm run build (Lint, Validate commits, Engine parity ×3, Test Node 22 ×3, Pre-publish benchmark gate, impact, CI Testing Pipeline, Embedding regression tests) fails downstream of the same ~70 TS2339/TS2694/TS7006 errors, all confined to ts-resolver.ts.

Runtime (verified locally, independent of the compile-time break): even if the type errors were silenced, (await import('typescript')).default at runtime under TS 7 only has {version, versionMajorMinor}ts.readConfigFile is undefined, so createProgram()'s try/catch swallows a TypeError and returns null. The feature would not crash, but would silently and permanently no-op for any project (including codegraph analyzing itself) where the installed typescript is v7+, discarding the compiler-verified (confidence 1.0) type enrichment this pass exists to provide, with only a debug()-level trace to indicate it happened.

Recommendation

This is not a small type-signature fix — it requires redesigning ts-resolver.ts's TSC integration around the new typescript/unstable/sync (or /async) client-server API: spawning/managing the compiler process, converting from tree-sitter node positions to DocumentIdentifier/NodeHandle lookups, and reworking every direct Program/Checker/Node call site (~70 call sites) to the new proxy-object model. This should be scoped as its own project, not bundled into a dependency-bump PR.

Until this is done, typescript should stay pinned below 7.0.0 (dependabot PR #2093 should not be merged as-is — recommend @dependabot ignore this major version on that PR until this issue is resolved).

Metadata

Metadata

Assignees

No one assigned

    Labels

    follow-upDeferred work from PR reviews that needs tracking

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions