withstudiocms / withstudiocms/expressive-code-twoslash
(Twoslash) Enhancement: Support TypeScript 7 (native Go port) — tracking + blockers
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 31
- Forks
- 8
- PR merge metrics
- No merged PRs in 30d
Description
Summary
With TypeScript 7 — the native Go port now shipping (typically 8–12× faster type-checking), it would be great for @ec-ts/twoslash, @ec-ts/twoslash-vue, @ec-ts/vfs, and expressive-code-twoslash to eventually support it.
This is a tracking issue, not a bug report. The native typescript@7 package doesn't yet expose the APIs Twoslash relies on, so I've documented the concrete blockers here rather than opening a premature PR. Happy to help implement once the upstream primitives are viable.
Current state
All three entry packages consume the classic TypeScript JS API:
@ec-ts/twoslash,@ec-ts/twoslash-vue, andexpressive-code-twoslashall doimport ts from "typescript"and pass it through astsModule.- The engine (
@ec-ts/twoslash/src/core.ts) and the VFS (@ec-ts/vfs) use the in-process LanguageService:getQuickInfoAtPosition,getCompletionsAtPosition,getSemanticDiagnostics/getSyntacticDiagnostics,getEmitOutput, plusts.sys,ts.optionDeclarations,ts.flattenDiagnosticMessageText,ts.versionMajorMinor, andcreateLanguageServiceover a virtualSystem.
There's already some version-aware handling (e.g. dropping baseUrl for TS ≥ 6 in core.ts), but TS 7 is a much larger shift than a compiler-option tweak.
Blockers with the native typescript@7 package
-
No classic entrypoint.
typescript@7.xexports only./package.jsonand./unstable/*— there is no./mainexport, andbinistsconly (notsserver). As a result,import ts from "typescript"throwsERR_PACKAGE_PATH_NOT_EXPORTED, so the packages fail to import (before any of their code runs) when a consumer is on TS 7. -
Different architecture. The
typescript/unstable/sync(and/async) API is an out-of-process client: anAPIthat spawns/sockets a native process via msgpack IPC, exposingSnapshot/Project/Program/Checker/Emitter. It's asynchronous at its core (the sync variant is aSharedArrayBuffer/Atomicschannel wrapper) and is explicitly markedunstable. -
Missing the primitives Twoslash depends on:
- Hovers — no
getQuickInfoAtPositionequivalent.CheckeroffersgetSymbolAtPosition/getTypeAtPosition/typeToString, so hover output would have to be reconstructed, and wouldn't reproduce the classicdisplayParts/ documentation / tags shape one-to-one. - Emit (
showEmit) — no LanguageServicegetEmitOutput; emit is limited toEmitter.printNode(AST → text), not transpile-to-JS of a virtual source file. - Diagnostics —
Program.getSemanticDiagnostics/getSyntacticDiagnosticsexist, but with a differentDiagnostic/ position /DocumentIdentifiermodel than the classic LanguageService output the code currently consumes. - VFS model mismatch —
@ec-ts/vfs'screateVirtualTypeScriptEnvironmentbuilds an in-memoryLanguageServiceHostover aMap-backedSystemand callscreateLanguageService. The native API has no in-memorySystem/createLanguageService; it uses a snapshot/document (LSP-style) model in a separate process.
- Hovers — no
Rough scope (for whenever this is viable)
- A native-backed environment in
@ec-ts/vfstargetingtypescript/unstable/sync(snapshot/document model instead ofcreateLanguageService). - A hover/quickinfo shim reconstructed from
Checkerprimitives. - Diagnostic + position adapters mapping onto the existing
twoslash-protocolnode shapes. - An emit path for
showEmit(or documenting it as unsupported under TS 7 initially). - Handling the async-native process (sync channel) and the churn of the
unstableAPI surface.
Given the size, this likely wants to wait until the native API stabilizes the LanguageService-style primitives (quickinfo / completions / emit), or ships a compatibility layer.
Interim suggestion (optional, low-risk)
Until then, consumers who happen to be on TS 7 hit a cryptic ERR_PACKAGE_PATH_NOT_EXPORTED. A small guard could improve the experience — e.g. tightening the typescript peer range (the catalog:min entry) to exclude v7, and/or emitting a clearer error when a non-classic tsModule is detected. Happy to open that as a separate, self-contained PR if it'd be welcome.
References
- TypeScript 7 announcement: https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/
- Native port background: https://devblogs.microsoft.com/typescript/typescript-native-port/
- typescript-eslint tracking the same class of blocker: typescript-eslint/typescript-eslint#10940 and typescript-eslint/typescript-eslint#12521
- ESLint async-parser dependency (their root blocker, not this project's): eslint/eslint#15475
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading @ec-ts/twoslash/src/core.ts and @ec-ts/vfs, then review the current TypeScript LanguageService calls and the typescript/unstable/sync API. This work is blocked by missing native quickinfo, emit, and compatibility primitives. Done would require a viable native-backed VFS plus hover, diagnostic, position, and emit adapters, or a documented unsupported path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100