February 21, 2019·4 min read·engineeringtypescripttoolingcompiler

TypeScript 3.3.3333 packages the compiler and editor service together

The February maintenance package supplies both tsc and tsserver. Its value is easier to understand through the distinct jobs of checking, emission and editor analysis.

TypeScript affects a program before JavaScript runs and while an author edits it. The same package supplies the command-line compiler and the service behind editor analysis. A maintenance update can therefore matter to a project even when it adds no new syntax that appears in the final application.

The npm registry records TypeScript 3.3.3333 at February 21, 2019, 22:20 UTC. Its release-tagged package metadata names both tsc and tsserver as executable entries. It also supplies lib/typescript.js as the programmatic entry and a corresponding declaration file.

Those facts define what this particular publication distributes. They do not imply a new language edition or a new JavaScript runtime. The package belongs to the 3.3 line, whose January announcement describes the checking and build behavior available in that release family.

I remain ambivalent about TypeScript, but the quality of its web tooling is a substantial part of its usefulness. An editor that understands relationships between functions and their callers can make a framework-heavy codebase easier to change. The compiler package matters because it supplies that analysis as well as the command that produces build output.

The package contains more than an emitter

The package's tsc executable is the command-line compiler entry. A programmatic entry allows other tools to use TypeScript as a library. The separate tsserver executable supports a service-oriented use of the same project. These are different integrations around the compiler's understanding of a program.

The 3.3 announcement describes definition navigation, finding references and automated refactorings as part of TypeScript's editor support. Those operations need relationships between source declarations and their uses. They are not equivalent to running the emitted JavaScript and observing its result.

That distinction helps explain why a compiler update has consequences during development. A change in analysis can affect which errors an author sees and which refactoring information an editor can obtain. The browser may still execute ordinary JavaScript, while the developer interacts with a different version of the analysis tool.

A package version gives those tool integrations a concrete identity. It does not establish which compiler an editor has selected in every installation. The important architectural point is that the published package contains the relevant executable entries, so editor and command-line work are both within its intended scope.

The 3.3 checker recognizes shared callable inputs

One concrete capability in this release family concerns a union of functions. Previously, the call signatures needed identical parameter lists in the supported simple case. TypeScript 3.3 can intersect eligible parameter types to find inputs that every possible function accepts.

For example, one callback might accept a string literal representing refresh or reset, while another accepts refresh or save. The shared refresh argument is valid regardless of which callback the variable contains. The result still has the union of the callbacks' return types because the input does not identify the chosen implementation.

The announcement explicitly limits this behavior around generic signatures and multiple overloads. Those restrictions are relevant to library consumers because method names can match while their callable types remain incompatible. The capability is a specific improvement in checking, not a promise to invoke every union of methods.

This is also an example of why TypeScript changes can improve a source program without introducing a runtime operation. The JavaScript function call already has its ordinary meaning. The checker becomes able to establish that the shared argument satisfies the declared possibilities, reducing the need for a manual assertion.

Composite watch builds reuse work within projects

The 3.3 line also connects composite watch builds to incremental file watching. The announcement distinguishes selecting projects affected by an edit from selecting files within one of those projects. Prior behavior could choose an affected project and still rebuild that project in full.

The incremental builder narrows checking and emission to changed files and files affected through dependencies. That makes project organization and file-level reuse complementary. Splitting a codebase into projects does not eliminate avoidable work inside each selected project.

A developer experiences this through repeated edits, where much of the program remains unchanged. The mechanism explains why update builds can differ from an initial build. It avoids attaching an unsupported universal speedup to the maintenance package or claiming a benchmark that has not been run for a particular application.

My preference is for this kind of tooling improvement to preserve the source program's meaning. Faster feedback is useful because it reduces the delay between an edit and the relevant compiler result. It should not require weakening the type relationships that made the check valuable.

JavaScript projects can use the analysis too

The announcement also states that TypeScript's editor support applies to JavaScript, including code described with JSDoc. Its Sublime Text plugin gains JavaScript editing support in the 3.3 release. That makes the analysis useful before a project converts all its source files to TypeScript.

The maintenance publication therefore belongs to a broader development-tool contract. It distributes a particular compiler and service implementation, with declared package entry points for their consumers. The 3.3 behaviors explain what those tools are meant to understand, while the exact package version identifies the implementation a project chooses to install.