Skip to content

API feature roadmap #4830

Description

These are the categories of remaining API features I think we need for 7.1, with a few specific items included below. Costs are very rough estimates and hopefully skew high.

This list does not include non-feature work like bug fixes, performance improvements, or docs, which are all important too.

1. TS Server Plugin Replacements

1A. Content mappers

1B. LSP client middleware registration

TS Server plugins have the ability to directly modify LS requests/responses. Existing TS 7 LSP/API integration only allows extensions to add TS-augmented providers, and cannot filter/modify any stock responses or alter the TS 7 editor behavior in any way. Our extension can expose a command or cross-extension API allowing other extensions to register callbacks that we can invoke in middleware in vscode-languageclient. (This is not a very well documented feature of the client, but it exists.)

  • Needed by: Angular (diagnostic filtering), likely others
  • Cost: 1 dev-week

2. Top-level utility APIs

Currently, almost all APIs require obtaining a snapshot containing a full program build of the project/files being worked on. This is a pretty good model for working within a tsconfig-defined project on disk, especially if needing to update the project over time, but awkward for many kinds of ad-hoc analysis; it’s not a natural substitute for ts.createProgram much less ts.createSourceFile.

This list is not exhaustive, but these are the top priority ones people have asked for.

2A. createProgram(options)

This will still be backed by a snapshot, but provides the opportunity to specify rootFiles and compilerOptions instead of needing to resolve a tsconfig file from disk. On the server side, I'm not sure whether the snapshot should be derived from an existing snapshot or should be built entirely from scratch. Either way, it should be an idempotent operation (other open projects not included in the returned snapshot, new snapshot not adopted by the project session). We’ll need to expose the underlying Project somehow (program.project parent pointer seems fine) and make the returned Program disposable (disposing its snapshot, since this API will guarantee 1:1 mapping between Program and Snapshot).

Note: This dovetails with 3B and may be better suited to be folded into that.

  • Needed by: likely ts-morph, many others
  • Cost: 1 dev-week

2B. createSourceFile(fileName, sourceText, options), createSourceFileFromFile(fileName, options)

Quick way to get an isolated AST from text or disk. Open question as to whether this can be truly stateless, or should be server-tracked to allow for a follow-up bindSourceFile, but the latter could be added in a backward-compatible way if needed. May be better to introduce a parameter indicating whether to send binder symbols back in the same response.

  • Needed by: ts-blank-space, likely ts-morph, many others
  • Cost: <1 dev-week

2C. transpileModule(sourceText, options), transpileModuleFromFile(fileName, options), transpileDeclaration(sourceText, options), transpileDeclarationFromFile(fileName, options)

Quick way to transpile TypeScript code to JavaScript or declaration files without needing a full program or project context.

3. CLI-wrapper APIs

We’ve discussed high-level APIs that would make it easy (or at least possible) to create a CLI tool that performs similar functions to tsc, with modifications that can only be achieved through API usage. Some of the scenarios motivating this will be handled by content mappers (#4712) instead, but I think Angular is still interested in this.

I’m treating --watch functionality as out of scope for now, because the TS 6 public API didn’t provide watching.

3A. parseCommandLine and related functions

High priority:

  • parseCommandLine(commandLine: readonly string[])
  • readConfigFile
  • parseJsonConfigFileContent(json, { configDirectory } | { configFileName })

Lower priority: other non-internal exported functions from commandLineParser.ts that have equivalents in Go

  • Needed by: Google
  • Cost: <1 dev-week

3B. Solution builder APIs, createIncrementalProgram

Budgeting more time for this because the API is built on top of the LSP server’s project layer, which currently does not integrate with the solution builder whatsoever. It may turn out to be simple, but it's a new integration point into a complex system.

  • Needed by: ts-loader, Bloomberg, Angular?
  • Cost: 2 dev-weeks

3C. Custom transformers

Much of the reason to create a CLI wrapper is making emit modifications. I think we can support an API very similar to Strada here by fetching the JS emit as a SourceFile (AST), running custom transformations client-side, and sending the transformed AST back to the server for final emit (basically printNode). I think the infrastructure to do this already exists, but may be missing a lot of emit-node metadata required to do proper comment preservation and formatting.

  • Needed by: Angular, Google, ts-loader
  • Cost: 2 dev-weeks (less for MVP)

3D. ts.formatDiagnostics, ts.formatDiagnosticsWithColorAndContext

formatDiagnostics can likely be a pure client-side port from Strada. The complication with formatDiagnosticsWithColorAndContext is that the source file text needed to create the context may or may not already be cached on the client. Having formatDiagnosticsWithColorAndContext be a dedicated remote API call probably makes sense.

  • Cost: <1 dev-week

4. General infrastructure

4A. VFS and overlay improvements

The included VFS implementation was meant only for testing, and includes no caching. There should be a way for the API client to provide file system contents eagerly and prevent IPC round-trips. This is easy implementation-wise, but finding the right design (particularly around invalidation, passthrough to disk, interaction with LSP-connected API) is important.

  • Needed by: Bloomberg, TypeScript playground
  • Cost: 1 dev-week

4B. Generic NodeHandle<T> and type guards on node handles

NodeHandle is currently non-generic, but would often be useful to carry narrowing information. A symbol.valueDeclaration.resolve() yields a Node when it could be a Declaration instead. This is easy, but also allowing a NodeHandle<Node> to be narrowed to a more specific NodeHandle type was surprisingly hard without code duplication or hacks. The likely path forward is giving in to code duplication or hacks and just getting it done.

  • Needed by: everyone
  • Cost: minimal for MVP

5. Additional methods in existing categories

There are still additional methods that can be exposed with no new concepts or infrastructure. The biggest categories are language service methods and small top-level utilities. The hardest part is just identifying them.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions